diff --git a/src/contracts/CLRatePriceCapAdapter.sol b/src/contracts/CLRatePriceCapAdapter.sol index 7d90ec2..a490220 100644 --- a/src/contracts/CLRatePriceCapAdapter.sol +++ b/src/contracts/CLRatePriceCapAdapter.sol @@ -19,9 +19,7 @@ contract CLRatePriceCapAdapter is PriceCapAdapterBase { * @param ratioProviderAddress the address of the (lstASSET / ASSET) ratio feed * @param pairName name identifier * @param minimumSnapshotDelay minimum time (in seconds) that should have passed from the snapshot timestamp to the current block.timestamp - * @param snapshotRatio the latest exchange ratio - * @param snapshotTimestamp the timestamp of the latest exchange ratio - * @param maxYearlyRatioGrowthPercent maximum growth of the underlying asset value per year, 100_00 is equal 100% + * @param priceCapParams parameters to set price cap */ constructor( IACLManager aclManager, @@ -29,9 +27,7 @@ contract CLRatePriceCapAdapter is PriceCapAdapterBase { address ratioProviderAddress, string memory pairName, uint48 minimumSnapshotDelay, - uint104 snapshotRatio, - uint48 snapshotTimestamp, - uint16 maxYearlyRatioGrowthPercent + PriceCapUpdateParams memory priceCapParams ) PriceCapAdapterBase( aclManager, @@ -40,9 +36,7 @@ contract CLRatePriceCapAdapter is PriceCapAdapterBase { pairName, IChainlinkAggregator(ratioProviderAddress).decimals(), minimumSnapshotDelay, - snapshotRatio, - snapshotTimestamp, - maxYearlyRatioGrowthPercent + priceCapParams ) {} diff --git a/src/contracts/CbETHPriceCapAdapter.sol b/src/contracts/CbETHPriceCapAdapter.sol index 6afecb7..1bfd42c 100644 --- a/src/contracts/CbETHPriceCapAdapter.sol +++ b/src/contracts/CbETHPriceCapAdapter.sol @@ -21,9 +21,7 @@ contract CbETHPriceCapAdapter is PriceCapAdapterBase { * @param ratioProviderAddress the address of the (cbETH / ETH) ratio provider * @param pairName name identifier * @param minimumSnapshotDelay minimum time (in seconds) that should have passed from the snapshot timestamp to the current block.timestamp - * @param snapshotRatio the latest exchange ratio - * @param snapshotTimestamp the timestamp of the latest exchange ratio - * @param maxYearlyRatioGrowthPercent maximum growth of the underlying asset value per year, 100_00 is equal 100% + * @param priceCapParams parameters to set price cap */ constructor( IACLManager aclManager, @@ -31,9 +29,7 @@ contract CbETHPriceCapAdapter is PriceCapAdapterBase { address ratioProviderAddress, string memory pairName, uint48 minimumSnapshotDelay, - uint104 snapshotRatio, - uint48 snapshotTimestamp, - uint16 maxYearlyRatioGrowthPercent + PriceCapUpdateParams memory priceCapParams ) PriceCapAdapterBase( aclManager, @@ -42,9 +38,7 @@ contract CbETHPriceCapAdapter is PriceCapAdapterBase { pairName, 18, minimumSnapshotDelay, - snapshotRatio, - snapshotTimestamp, - maxYearlyRatioGrowthPercent + priceCapParams ) {} diff --git a/src/contracts/MaticPriceCapAdapter.sol b/src/contracts/MaticPriceCapAdapter.sol index b93ab61..8b04c7d 100644 --- a/src/contracts/MaticPriceCapAdapter.sol +++ b/src/contracts/MaticPriceCapAdapter.sol @@ -20,9 +20,7 @@ contract MaticPriceCapAdapter is PriceCapAdapterBase { * @param ratioProviderAddress the address of (lst Matic / MATIC) pair ratio feed * @param pairName name identifier * @param minimumSnapshotDelay minimum time (in seconds) that should have passed from the snapshot timestamp to the current block.timestamp - * @param snapshotRatio the latest exchange ratio - * @param snapshotTimestamp the timestamp of the latest exchange ratio - * @param maxYearlyRatioGrowthPercent maximum growth of the underlying asset value per year, 100_00 is equal 100% + * @param priceCapParams parameters to set price cap */ constructor( IACLManager aclManager, @@ -30,9 +28,7 @@ contract MaticPriceCapAdapter is PriceCapAdapterBase { address ratioProviderAddress, string memory pairName, uint48 minimumSnapshotDelay, - uint104 snapshotRatio, - uint48 snapshotTimestamp, - uint16 maxYearlyRatioGrowthPercent + PriceCapUpdateParams memory priceCapParams ) PriceCapAdapterBase( aclManager, @@ -41,9 +37,7 @@ contract MaticPriceCapAdapter is PriceCapAdapterBase { pairName, 18, minimumSnapshotDelay, - snapshotRatio, - snapshotTimestamp, - maxYearlyRatioGrowthPercent + priceCapParams ) {} diff --git a/src/contracts/PriceCapAdapterBase.sol b/src/contracts/PriceCapAdapterBase.sol index 2226c87..641215e 100644 --- a/src/contracts/PriceCapAdapterBase.sol +++ b/src/contracts/PriceCapAdapterBase.sol @@ -68,9 +68,7 @@ abstract contract PriceCapAdapterBase is IPriceCapAdapter { * @param pairDescription the capped (lstAsset / underlyingAsset) pair description * @param ratioDecimals the number of decimal places of the (lstAsset / underlyingAsset) ratio feed * @param minimumSnapshotDelay minimum time (in seconds) that should have passed from the snapshot timestamp to the current block.timestamp - * @param snapshotRatio the latest exchange ratio - * @param snapshotTimestamp the timestamp of the latest exchange ratio - * @param maxYearlyRatioGrowthPercent maximum growth of the underlying asset value per year, 100_00 is equal 100% + * @param priceCapParams parameters to set price cap */ constructor( IACLManager aclManager, @@ -79,9 +77,7 @@ abstract contract PriceCapAdapterBase is IPriceCapAdapter { string memory pairDescription, uint8 ratioDecimals, uint48 minimumSnapshotDelay, - uint104 snapshotRatio, - uint48 snapshotTimestamp, - uint16 maxYearlyRatioGrowthPercent + PriceCapUpdateParams memory priceCapParams ) { if (address(aclManager) == address(0)) { revert ACLManagerIsZeroAddress(); @@ -95,7 +91,7 @@ abstract contract PriceCapAdapterBase is IPriceCapAdapter { _description = pairDescription; - _setCapParameters(snapshotRatio, snapshotTimestamp, maxYearlyRatioGrowthPercent); + _setCapParameters(priceCapParams); } /// @inheritdoc ICLSynchronicityPriceAdapter @@ -129,16 +125,12 @@ abstract contract PriceCapAdapterBase is IPriceCapAdapter { } /// @inheritdoc IPriceCapAdapter - function setCapParameters( - uint104 snapshotRatio, - uint48 snapshotTimestamp, - uint16 maxYearlyRatioGrowthPercent - ) external { + function setCapParameters(PriceCapUpdateParams memory priceCapParams) external { if (!ACL_MANAGER.isRiskAdmin(msg.sender) && !ACL_MANAGER.isPoolAdmin(msg.sender)) { revert CallerIsNotRiskOrPoolAdmin(); } - _setCapParameters(snapshotRatio, snapshotTimestamp, maxYearlyRatioGrowthPercent); + _setCapParameters(priceCapParams); } /// @inheritdoc ICLSynchronicityPriceAdapter @@ -167,29 +159,31 @@ abstract contract PriceCapAdapterBase is IPriceCapAdapter { return price; } - function _setCapParameters( - uint104 snapshotRatio, - uint48 snapshotTimestamp, - uint16 maxYearlyRatioGrowthPercent - ) internal { + /** + * @notice Updates price cap parameters + * @param priceCapParams parameters to set price cap + */ + function _setCapParameters(PriceCapUpdateParams memory priceCapParams) internal { // if snapshot ratio is 0 then growth will not work as expected - if (snapshotRatio == 0) { + if (priceCapParams.snapshotRatio == 0) { revert SnapshotRatioIsZero(); } // new snapshot timestamp should be gt then stored one, but not gt then timestamp of the current block if ( - _snapshotTimestamp >= snapshotTimestamp || - snapshotTimestamp > block.timestamp - MINIMUM_SNAPSHOT_DELAY + _snapshotTimestamp >= priceCapParams.snapshotTimestamp || + priceCapParams.snapshotTimestamp > block.timestamp - MINIMUM_SNAPSHOT_DELAY ) { - revert InvalidRatioTimestamp(snapshotTimestamp); + revert InvalidRatioTimestamp(priceCapParams.snapshotTimestamp); } - _snapshotRatio = snapshotRatio; - _snapshotTimestamp = snapshotTimestamp; - _maxYearlyRatioGrowthPercent = maxYearlyRatioGrowthPercent; + _snapshotRatio = priceCapParams.snapshotRatio; + _snapshotTimestamp = priceCapParams.snapshotTimestamp; + _maxYearlyRatioGrowthPercent = priceCapParams.maxYearlyRatioGrowthPercent; _maxRatioGrowthPerSecond = uint104( - (uint256(snapshotRatio) * maxYearlyRatioGrowthPercent) / PERCENTAGE_FACTOR / SECONDS_PER_YEAR + (uint256(priceCapParams.snapshotRatio) * priceCapParams.maxYearlyRatioGrowthPercent) / + PERCENTAGE_FACTOR / + SECONDS_PER_YEAR ); // if the ratio on the current growth speed can overflow less then in a MINIMAL_RATIO_INCREASE_LIFETIME years, revert @@ -198,14 +192,17 @@ abstract contract PriceCapAdapterBase is IPriceCapAdapter { (_maxRatioGrowthPerSecond * SECONDS_PER_YEAR * MINIMAL_RATIO_INCREASE_LIFETIME) > type(uint104).max ) { - revert SnapshotMayOverflowSoon(snapshotRatio, maxYearlyRatioGrowthPercent); + revert SnapshotMayOverflowSoon( + priceCapParams.snapshotRatio, + priceCapParams.maxYearlyRatioGrowthPercent + ); } emit CapParametersUpdated( - snapshotRatio, - snapshotTimestamp, + priceCapParams.snapshotRatio, + priceCapParams.snapshotTimestamp, _maxRatioGrowthPerSecond, - maxYearlyRatioGrowthPercent + priceCapParams.maxYearlyRatioGrowthPercent ); } diff --git a/src/contracts/RETHPriceCapAdapter.sol b/src/contracts/RETHPriceCapAdapter.sol index 2810535..8acd8ae 100644 --- a/src/contracts/RETHPriceCapAdapter.sol +++ b/src/contracts/RETHPriceCapAdapter.sol @@ -19,9 +19,7 @@ contract RETHPriceCapAdapter is PriceCapAdapterBase { * @param rETHAddress the address of the rETH token, the (rETH / ETH) ratio feed * @param pairName name identifier * @param minimumSnapshotDelay minimum time (in seconds) that should have passed from the snapshot timestamp to the current block.timestamp - * @param snapshotRatio the latest exchange ratio - * @param snapshotTimestamp the timestamp of the latest exchange ratio - * @param maxYearlyRatioGrowthPercent maximum growth of the underlying asset value per year, 100_00 is equal 100% + * @param priceCapParams parameters to set price cap */ constructor( IACLManager aclManager, @@ -29,9 +27,7 @@ contract RETHPriceCapAdapter is PriceCapAdapterBase { address rETHAddress, string memory pairName, uint48 minimumSnapshotDelay, - uint104 snapshotRatio, - uint48 snapshotTimestamp, - uint16 maxYearlyRatioGrowthPercent + PriceCapUpdateParams memory priceCapParams ) PriceCapAdapterBase( aclManager, @@ -40,9 +36,7 @@ contract RETHPriceCapAdapter is PriceCapAdapterBase { pairName, 18, minimumSnapshotDelay, - snapshotRatio, - snapshotTimestamp, - maxYearlyRatioGrowthPercent + priceCapParams ) {} diff --git a/src/contracts/SAvaxPriceCapAdapter.sol b/src/contracts/SAvaxPriceCapAdapter.sol index d930ce0..40d4c2c 100644 --- a/src/contracts/SAvaxPriceCapAdapter.sol +++ b/src/contracts/SAvaxPriceCapAdapter.sol @@ -19,9 +19,7 @@ contract SAvaxPriceCapAdapter is PriceCapAdapterBase { * @param sAVAXAddress the address of the sAVAX token, the (sAVAX / AVAX) ratio feed * @param pairName name identifier * @param minimumSnapshotDelay minimum time (in seconds) that should have passed from the snapshot timestamp to the current block.timestamp - * @param snapshotRatio the latest exchange ratio - * @param snapshotTimestamp the timestamp of the latest exchange ratio - * @param maxYearlyRatioGrowthPercent maximum growth of the underlying asset value per year, 100_00 is equal 100% + * @param priceCapParams parameters to set price cap */ constructor( IACLManager aclManager, @@ -29,9 +27,7 @@ contract SAvaxPriceCapAdapter is PriceCapAdapterBase { address sAVAXAddress, string memory pairName, uint48 minimumSnapshotDelay, - uint104 snapshotRatio, - uint48 snapshotTimestamp, - uint16 maxYearlyRatioGrowthPercent + PriceCapUpdateParams memory priceCapParams ) PriceCapAdapterBase( aclManager, @@ -40,9 +36,7 @@ contract SAvaxPriceCapAdapter is PriceCapAdapterBase { pairName, 18, minimumSnapshotDelay, - snapshotRatio, - snapshotTimestamp, - maxYearlyRatioGrowthPercent + priceCapParams ) {} diff --git a/src/contracts/SDAIGnosisPriceCapAdapter.sol b/src/contracts/SDAIGnosisPriceCapAdapter.sol index 6d608d3..85fc18b 100644 --- a/src/contracts/SDAIGnosisPriceCapAdapter.sol +++ b/src/contracts/SDAIGnosisPriceCapAdapter.sol @@ -19,9 +19,7 @@ contract SDAIGnosisPriceCapAdapter is PriceCapAdapterBase { * @param sDaiAddress the address of the sDAI, used as the (sDAI / DAI) ratio feed * @param pairName name identifier * @param minimumSnapshotDelay minimum time (in seconds) that should have passed from the snapshot timestamp to the current block.timestamp - * @param snapshotRatio The latest exchange ratio - * @param snapshotTimestamp The timestamp of the latest exchange ratio - * @param maxYearlyRatioGrowthPercent Maximum growth of the underlying asset value per year, 100_00 is equal 100% + * @param priceCapParams parameters to set price cap */ constructor( IACLManager aclManager, @@ -29,9 +27,7 @@ contract SDAIGnosisPriceCapAdapter is PriceCapAdapterBase { address sDaiAddress, string memory pairName, uint48 minimumSnapshotDelay, - uint104 snapshotRatio, - uint48 snapshotTimestamp, - uint16 maxYearlyRatioGrowthPercent + PriceCapUpdateParams memory priceCapParams ) PriceCapAdapterBase( aclManager, @@ -40,9 +36,7 @@ contract SDAIGnosisPriceCapAdapter is PriceCapAdapterBase { pairName, IERC4626(sDaiAddress).decimals(), minimumSnapshotDelay, - snapshotRatio, - snapshotTimestamp, - maxYearlyRatioGrowthPercent + priceCapParams ) {} diff --git a/src/contracts/SDAIPriceCapAdapter.sol b/src/contracts/SDAIPriceCapAdapter.sol index 2f1f067..5be0a50 100644 --- a/src/contracts/SDAIPriceCapAdapter.sol +++ b/src/contracts/SDAIPriceCapAdapter.sol @@ -19,9 +19,7 @@ contract SDAIPriceCapAdapter is PriceCapAdapterBase { * @param potAddress the address of the sDAI pot, used the (sDAI / DAI) ratio feed * @param pairName name identifier * @param minimumSnapshotDelay minimum time (in seconds) that should have passed from the snapshot timestamp to the current block.timestamp - * @param snapshotRatio the latest exchange ratio - * @param snapshotTimestamp the timestamp of the latest exchange ratio - * @param maxYearlyRatioGrowthPercent maximum growth of the underlying asset value per year, 100_00 is equal 100% + * @param priceCapParams parameters to set price cap */ constructor( IACLManager aclManager, @@ -29,9 +27,7 @@ contract SDAIPriceCapAdapter is PriceCapAdapterBase { address potAddress, string memory pairName, uint48 minimumSnapshotDelay, - uint104 snapshotRatio, - uint48 snapshotTimestamp, - uint16 maxYearlyRatioGrowthPercent + PriceCapUpdateParams memory priceCapParams ) PriceCapAdapterBase( aclManager, @@ -40,9 +36,7 @@ contract SDAIPriceCapAdapter is PriceCapAdapterBase { pairName, 27, minimumSnapshotDelay, - snapshotRatio, - snapshotTimestamp, - maxYearlyRatioGrowthPercent + priceCapParams ) {} diff --git a/src/contracts/WstETHPriceCapAdapter.sol b/src/contracts/WstETHPriceCapAdapter.sol index 2086d29..8a8aced 100644 --- a/src/contracts/WstETHPriceCapAdapter.sol +++ b/src/contracts/WstETHPriceCapAdapter.sol @@ -19,9 +19,7 @@ contract WstETHPriceCapAdapter is PriceCapAdapterBase { * @param stEthAddress the address of the stETH contract, the (wStETH / ETH) ratio feed * @param pairName name identifier * @param minimumSnapshotDelay minimum time (in seconds) that should have passed from the snapshot timestamp to the current block.timestamp - * @param snapshotRatio the latest exchange ratio - * @param snapshotTimestamp the timestamp of the latest exchange ratio - * @param maxYearlyRatioGrowthPercent maximum growth of the underlying asset value per year, 100_00 is equal 100% + * @param priceCapParams parameters to set price cap */ constructor( IACLManager aclManager, @@ -29,9 +27,7 @@ contract WstETHPriceCapAdapter is PriceCapAdapterBase { address stEthAddress, string memory pairName, uint48 minimumSnapshotDelay, - uint104 snapshotRatio, - uint48 snapshotTimestamp, - uint16 maxYearlyRatioGrowthPercent + PriceCapUpdateParams memory priceCapParams ) PriceCapAdapterBase( aclManager, @@ -40,9 +36,7 @@ contract WstETHPriceCapAdapter is PriceCapAdapterBase { pairName, 18, minimumSnapshotDelay, - snapshotRatio, - snapshotTimestamp, - maxYearlyRatioGrowthPercent + priceCapParams ) {} diff --git a/src/interfaces/IPriceCapAdapter.sol b/src/interfaces/IPriceCapAdapter.sol index 62b4be6..5ae544f 100644 --- a/src/interfaces/IPriceCapAdapter.sol +++ b/src/interfaces/IPriceCapAdapter.sol @@ -20,17 +20,21 @@ interface IPriceCapAdapter is ICLSynchronicityPriceAdapter { uint16 maxYearlyRatioGrowthPercent ); + /** + * @notice Parameters to update price cap + * @param priceCapParams parameters to set price cap + */ + struct PriceCapUpdateParams { + uint104 snapshotRatio; + uint48 snapshotTimestamp; + uint16 maxYearlyRatioGrowthPercent; + } + /** * @notice Updates price cap parameters - * @param snapshotRatio the latest exchange ratio - * @param snapshotTimestamp the timestamp of the latest exchange ratio - * @param maxYearlyRatioGrowthPercent maximum growth of the underlying asset value per year, 100_00 is equal 100% + * @param priceCapParams parameters to set price cap */ - function setCapParameters( - uint104 snapshotRatio, - uint48 snapshotTimestamp, - uint16 maxYearlyRatioGrowthPercent - ) external; + function setCapParameters(PriceCapUpdateParams memory priceCapParams) external; /** * @notice Maximum percentage factor (100.00%) diff --git a/tests/BaseTest.sol b/tests/BaseTest.sol index 886a06e..f78ab4f 100644 --- a/tests/BaseTest.sol +++ b/tests/BaseTest.sol @@ -13,6 +13,15 @@ abstract contract BaseTest is Test { NOT_CAPPED_ADAPTER = ICLSynchronicityPriceAdapter(notCappedAdapter); } + function createAdapter( + IACLManager aclManager, + address baseAggregatorAddress, + address ratioProviderAddress, + string memory pairDescription, + uint48 minimumSnapshotDelay, + IPriceCapAdapter.PriceCapUpdateParams memory priceCapParams + ) public virtual returns (IPriceCapAdapter); + function createAdapter( IACLManager aclManager, address baseAggregatorAddress, @@ -22,7 +31,22 @@ abstract contract BaseTest is Test { uint104 snapshotRatio, uint48 snapshotTimestamp, uint16 maxYearlyRatioGrowthPercent - ) public virtual returns (IPriceCapAdapter); + ) public virtual returns (IPriceCapAdapter) { + IPriceCapAdapter.PriceCapUpdateParams memory priceCapParams; + priceCapParams.snapshotRatio = snapshotRatio; + priceCapParams.snapshotTimestamp = snapshotTimestamp; + priceCapParams.maxYearlyRatioGrowthPercent = maxYearlyRatioGrowthPercent; + + return + createAdapter( + aclManager, + baseAggregatorAddress, + ratioProviderAddress, + pairDescription, + minimumSnapshotDelay, + priceCapParams + ); + } function createAdapterSimple( uint48 minimumSnapshotDelay, @@ -45,6 +69,19 @@ abstract contract BaseTest is Test { uint16 maxYearlyRatioGrowthPercent ) public virtual returns (IPriceCapAdapter); + function setCapParameters( + IPriceCapAdapter adapter, + uint104 currentRatio, + uint48 snapshotTimestamp, + uint16 maxYearlyRatioGrowthPercent + ) public { + IPriceCapAdapter.PriceCapUpdateParams memory priceCapParams; + priceCapParams.snapshotRatio = currentRatio; + priceCapParams.snapshotTimestamp = snapshotTimestamp; + priceCapParams.maxYearlyRatioGrowthPercent = maxYearlyRatioGrowthPercent; + adapter.setCapParameters(priceCapParams); + } + function getCurrentRatio() public view virtual returns (uint104); function deploySimpleAndSetParams( @@ -65,7 +102,8 @@ abstract contract BaseTest is Test { abi.encodeWithSelector(BasicIACLManager.isRiskAdmin.selector), abi.encode(true) ); - adapter.setCapParameters( + setCapParameters( + adapter, uint104(adapter.getSnapshotRatio()) + 1, uint48(block.timestamp) - minimumSnapshotDelay, maxYearlyRatioGrowthPercentUpdated @@ -162,7 +200,8 @@ abstract contract BaseTest is Test { abi.encodeWithSelector(BasicIACLManager.isRiskAdmin.selector), abi.encode(true) ); - adapter.setCapParameters( + setCapParameters( + adapter, uint104(adapter.getSnapshotRatio()) + 1, uint48(block.timestamp) - minimumSnapshotDelay, maxYearlyRatioGrowthPercentUpdated @@ -207,7 +246,7 @@ abstract contract BaseTest is Test { vm.expectRevert( abi.encodeWithSelector(IPriceCapAdapter.InvalidRatioTimestamp.selector, timestampUpdate) ); - adapter.setCapParameters(1, timestampUpdate, 1); + setCapParameters(adapter, 1, timestampUpdate, 1); } function test_revert_constructor_current_ratio_is_0( @@ -235,10 +274,10 @@ abstract contract BaseTest is Test { abi.encode(false) ); vm.expectRevert(IPriceCapAdapter.CallerIsNotRiskOrPoolAdmin.selector); - adapter.setCapParameters(1, 1, 1); + setCapParameters(adapter, 1, 1, 1); } - function test_latestAnswer(uint16 maxYearlyRatioGrowthPercent) public { + function test_latestAnswer(uint16 maxYearlyRatioGrowthPercent) public virtual { IPriceCapAdapter adapter = createAdapterSimple( 0, uint40(block.timestamp), @@ -248,6 +287,10 @@ abstract contract BaseTest is Test { int256 price = adapter.latestAnswer(); int256 priceOfNotCappedAdapter = NOT_CAPPED_ADAPTER.latestAnswer(); - assertEq(price, priceOfNotCappedAdapter); + assertEq( + price, + priceOfNotCappedAdapter, + 'uncapped price is not equal to the existing adapter price' + ); } } diff --git a/tests/CbETHPriceCapAdapterTest.t.sol b/tests/CbETHPriceCapAdapterTest.t.sol index b1d4391..b5034d9 100644 --- a/tests/CbETHPriceCapAdapterTest.t.sol +++ b/tests/CbETHPriceCapAdapterTest.t.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.0; -import {Test} from 'forge-std/Test.sol'; +import './BaseTest.sol'; import {AaveV3Ethereum, AaveV3EthereumAssets} from 'aave-address-book/AaveV3Ethereum.sol'; import {BaseAggregatorsMainnet} from 'cl-synchronicity-price-adapter/lib/BaseAggregators.sol'; @@ -9,34 +9,83 @@ import {BaseAggregatorsMainnet} from 'cl-synchronicity-price-adapter/lib/BaseAgg import {CbETHPriceCapAdapter, ICbEthRateProvider} from '../src/contracts/CbETHPriceCapAdapter.sol'; import {ICLSynchronicityPriceAdapter} from '../src/interfaces/IPriceCapAdapter.sol'; -contract CbETHPriceCapAdapterTest is Test { - ICLSynchronicityPriceAdapter public constant notCappedAdapter = - ICLSynchronicityPriceAdapter(AaveV3EthereumAssets.cbETH_ORACLE); +contract CbETHPriceCapAdapterTest is BaseTest { + constructor() BaseTest(AaveV3EthereumAssets.cbETH_ORACLE) {} + + function createAdapter( + IACLManager aclManager, + address baseAggregatorAddress, + address ratioProviderAddress, + string memory pairDescription, + uint48 minimumSnapshotDelay, + IPriceCapAdapter.PriceCapUpdateParams memory priceCapParams + ) public override returns (IPriceCapAdapter) { + return + new CbETHPriceCapAdapter( + aclManager, + baseAggregatorAddress, + ratioProviderAddress, + pairDescription, + minimumSnapshotDelay, + priceCapParams + ); + } + + function createAdapterSimple( + uint48 minimumSnapshotDelay, + uint104 currentRatio, + uint48 snapshotTimestamp, + uint16 maxYearlyRatioGrowthPercent + ) public override returns (IPriceCapAdapter) { + return + createAdapter( + AaveV3Ethereum.ACL_MANAGER, + BaseAggregatorsMainnet.ETH_USD_AGGREGATOR, + BaseAggregatorsMainnet.CBETH, + 'cbETH / ETH / USD', + minimumSnapshotDelay, + currentRatio, + snapshotTimestamp, + maxYearlyRatioGrowthPercent + ); + } + + function getCurrentRatio() public view override returns (uint104) { + return uint104(ICbEthRateProvider(BaseAggregatorsMainnet.CBETH).exchangeRate()); + } function setUp() public { vm.createSelectFork(vm.rpcUrl('mainnet'), 18961286); } - // function test_latestAnswer(uint16 maxPercent) public { - // CbETHPriceCapAdapter adapter = new CbETHPriceCapAdapter( - // AaveV3Ethereum.ACL_MANAGER, - // BaseAggregatorsMainnet.ETH_USD_AGGREGATOR, - // BaseAggregatorsMainnet.CBETH, - // 'cbETH / ETH / USD', - // // TODO: should be adjusted after we decide with source - // uint104(ICbEthRateProvider(BaseAggregatorsMainnet.CBETH).exchangeRate()), - // uint48(block.timestamp), - // maxPercent - // ); - // - // int256 price = adapter.latestAnswer(); - // int256 priceOfNotCappedAdapter = notCappedAdapter.latestAnswer(); - // - // assertEq(price, priceOfNotCappedAdapter); - // } + function test_latestAnswer(uint16 maxYearlyRatioGrowthPercent) public override { + IPriceCapAdapter adapter = createAdapterSimple( + 0, + uint40(block.timestamp), + maxYearlyRatioGrowthPercent + ); + + int256 price = adapter.latestAnswer(); + + // here we have a very specific case, because we replace secondary-market based CL feed of exchange rate + // with the primary cbETH based feed + uint256 cbEthRate = getCurrentRatio(); + vm.mockCall( + BaseAggregatorsMainnet.CBETH_ETH_AGGREGATOR, + abi.encodeWithSelector(ICLSynchronicityPriceAdapter.latestAnswer.selector), + abi.encode(int256(cbEthRate)) + ); + int256 priceOfNotCappedAdapter = NOT_CAPPED_ADAPTER.latestAnswer(); + + assertEq( + price, + priceOfNotCappedAdapter, + 'uncapped price is not equal to the existing adapter price' + ); + } function test_cappedLatestAnswer() public { - CbETHPriceCapAdapter adapter = new CbETHPriceCapAdapter( + IPriceCapAdapter adapter = createAdapter( AaveV3Ethereum.ACL_MANAGER, BaseAggregatorsMainnet.ETH_USD_AGGREGATOR, BaseAggregatorsMainnet.CBETH, diff --git a/tests/MaticPriceCapAdapterTest.t.sol b/tests/MaticPriceCapAdapterTest.t.sol index d495bd0..f8ed1fe 100644 --- a/tests/MaticPriceCapAdapterTest.t.sol +++ b/tests/MaticPriceCapAdapterTest.t.sol @@ -27,9 +27,7 @@ abstract contract BaseMaticPriceCapAdapterTest is BaseTest { address ratioProviderAddress, string memory pairDescription, uint48 minimumSnapshotDelay, - uint104 snapshotRatio, - uint48 snapshotTimestamp, - uint16 maxYearlyRatioGrowthPercent + IPriceCapAdapter.PriceCapUpdateParams memory priceCapParams ) public override returns (IPriceCapAdapter) { return new MaticPriceCapAdapter( @@ -38,9 +36,7 @@ abstract contract BaseMaticPriceCapAdapterTest is BaseTest { ratioProviderAddress, pairDescription, minimumSnapshotDelay, - snapshotRatio, - snapshotTimestamp, - maxYearlyRatioGrowthPercent + priceCapParams ); } @@ -51,7 +47,7 @@ abstract contract BaseMaticPriceCapAdapterTest is BaseTest { uint16 maxYearlyRatioGrowthPercent ) public override returns (IPriceCapAdapter) { return - new MaticPriceCapAdapter( + createAdapter( AaveV3Polygon.ACL_MANAGER, BaseAggregatorsPolygon.MATIC_USD_AGGREGATOR, RATE_PROVIDER, diff --git a/tests/RETHPriceCapAdapterTest.t.sol b/tests/RETHPriceCapAdapterTest.t.sol index a56f5c4..04c70c8 100644 --- a/tests/RETHPriceCapAdapterTest.t.sol +++ b/tests/RETHPriceCapAdapterTest.t.sol @@ -18,9 +18,7 @@ contract RETHPriceCapAdapterTest is BaseTest { address ratioProviderAddress, string memory pairDescription, uint48 minimumSnapshotDelay, - uint104 snapshotRatio, - uint48 snapshotTimestamp, - uint16 maxYearlyRatioGrowthPercent + IPriceCapAdapter.PriceCapUpdateParams memory priceCapParams ) public override returns (IPriceCapAdapter) { return new RETHPriceCapAdapter( @@ -29,9 +27,7 @@ contract RETHPriceCapAdapterTest is BaseTest { ratioProviderAddress, pairDescription, minimumSnapshotDelay, - snapshotRatio, - snapshotTimestamp, - maxYearlyRatioGrowthPercent + priceCapParams ); } @@ -42,7 +38,7 @@ contract RETHPriceCapAdapterTest is BaseTest { uint16 maxYearlyRatioGrowthPercent ) public override returns (IPriceCapAdapter) { return - new RETHPriceCapAdapter( + createAdapter( AaveV3Ethereum.ACL_MANAGER, BaseAggregatorsMainnet.ETH_USD_AGGREGATOR, MissingAssetsMainnet.RETH, @@ -63,7 +59,7 @@ contract RETHPriceCapAdapterTest is BaseTest { } function test_cappedLatestAnswer() public { - RETHPriceCapAdapter adapter = new RETHPriceCapAdapter( + IPriceCapAdapter adapter = createAdapter( AaveV3Ethereum.ACL_MANAGER, BaseAggregatorsMainnet.ETH_USD_AGGREGATOR, MissingAssetsMainnet.RETH, diff --git a/tests/SAvaxPriceCapAdapterTest.t.sol b/tests/SAvaxPriceCapAdapterTest.t.sol index 0df80a8..355508f 100644 --- a/tests/SAvaxPriceCapAdapterTest.t.sol +++ b/tests/SAvaxPriceCapAdapterTest.t.sol @@ -17,9 +17,7 @@ contract SAvaxPriceCapAdapterTest is BaseTest { address ratioProviderAddress, string memory pairDescription, uint48 minimumSnapshotDelay, - uint104 snapshotRatio, - uint48 snapshotTimestamp, - uint16 maxYearlyRatioGrowthPercent + IPriceCapAdapter.PriceCapUpdateParams memory priceCapParams ) public override returns (IPriceCapAdapter) { return new SAvaxPriceCapAdapter( @@ -28,9 +26,7 @@ contract SAvaxPriceCapAdapterTest is BaseTest { ratioProviderAddress, pairDescription, minimumSnapshotDelay, - snapshotRatio, - snapshotTimestamp, - maxYearlyRatioGrowthPercent + priceCapParams ); } @@ -41,7 +37,7 @@ contract SAvaxPriceCapAdapterTest is BaseTest { uint16 maxYearlyRatioGrowthPercent ) public override returns (IPriceCapAdapter) { return - new SAvaxPriceCapAdapter( + createAdapter( AaveV3Avalanche.ACL_MANAGER, AaveV3AvalancheAssets.WAVAX_ORACLE, AaveV3AvalancheAssets.sAVAX_UNDERLYING, diff --git a/tests/SDAIGnosisPriceCapAdapterTest.t.sol b/tests/SDAIGnosisPriceCapAdapterTest.t.sol index 7650b81..484fc11 100644 --- a/tests/SDAIGnosisPriceCapAdapterTest.t.sol +++ b/tests/SDAIGnosisPriceCapAdapterTest.t.sol @@ -18,9 +18,7 @@ contract SDAIGnosisPriceCapAdapterTest is BaseTest { address ratioProviderAddress, string memory pairDescription, uint48 minimumSnapshotDelay, - uint104 snapshotRatio, - uint48 snapshotTimestamp, - uint16 maxYearlyRatioGrowthPercent + IPriceCapAdapter.PriceCapUpdateParams memory priceCapParams ) public override returns (IPriceCapAdapter) { return new SDAIGnosisPriceCapAdapter( @@ -29,9 +27,7 @@ contract SDAIGnosisPriceCapAdapterTest is BaseTest { ratioProviderAddress, pairDescription, minimumSnapshotDelay, - snapshotRatio, - snapshotTimestamp, - maxYearlyRatioGrowthPercent + priceCapParams ); } @@ -42,7 +38,7 @@ contract SDAIGnosisPriceCapAdapterTest is BaseTest { uint16 maxYearlyRatioGrowthPercent ) public override returns (IPriceCapAdapter) { return - new SDAIGnosisPriceCapAdapter( + createAdapter( AaveV3Gnosis.ACL_MANAGER, BaseAggregatorsGnosis.DAI_USD_AGGREGATOR, AaveV3GnosisAssets.sDAI_UNDERLYING, diff --git a/tests/SDAIPriceCapAdapterTest.t.sol b/tests/SDAIPriceCapAdapterTest.t.sol index c1b2dbc..a2cd3e7 100644 --- a/tests/SDAIPriceCapAdapterTest.t.sol +++ b/tests/SDAIPriceCapAdapterTest.t.sol @@ -17,9 +17,7 @@ contract SDAIPriceCapAdapterTest is BaseTest { address ratioProviderAddress, string memory pairDescription, uint48 minimumSnapshotDelay, - uint104 snapshotRatio, - uint48 snapshotTimestamp, - uint16 maxYearlyRatioGrowthPercent + IPriceCapAdapter.PriceCapUpdateParams memory priceCapParams ) public override returns (IPriceCapAdapter) { return new SDAIPriceCapAdapter( @@ -28,9 +26,7 @@ contract SDAIPriceCapAdapterTest is BaseTest { ratioProviderAddress, pairDescription, minimumSnapshotDelay, - snapshotRatio, - snapshotTimestamp, - maxYearlyRatioGrowthPercent + priceCapParams ); } @@ -41,7 +37,7 @@ contract SDAIPriceCapAdapterTest is BaseTest { uint16 maxYearlyRatioGrowthPercent ) public override returns (IPriceCapAdapter) { return - new SDAIPriceCapAdapter( + createAdapter( AaveV3Ethereum.ACL_MANAGER, BaseAggregatorsMainnet.DAI_USD_AGGREGATOR, BaseAggregatorsMainnet.SDAI_POT, @@ -62,7 +58,7 @@ contract SDAIPriceCapAdapterTest is BaseTest { } function test_cappedLatestAnswer() public { - SDAIPriceCapAdapter adapter = new SDAIPriceCapAdapter( + IPriceCapAdapter adapter = createAdapter( AaveV3Ethereum.ACL_MANAGER, BaseAggregatorsMainnet.DAI_USD_AGGREGATOR, BaseAggregatorsMainnet.SDAI_POT, diff --git a/tests/WstETHPriceCapAdapterTest.t.sol b/tests/WstETHPriceCapAdapterTest.t.sol index 338e0d2..7f38e5c 100644 --- a/tests/WstETHPriceCapAdapterTest.t.sol +++ b/tests/WstETHPriceCapAdapterTest.t.sol @@ -19,9 +19,7 @@ contract WstETHPriceCapAdapterTest is BaseTest { address ratioProviderAddress, string memory pairDescription, uint48 minimumSnapshotDelay, - uint104 snapshotRatio, - uint48 snapshotTimestamp, - uint16 maxYearlyRatioGrowthPercent + IPriceCapAdapter.PriceCapUpdateParams memory priceCapParams ) public override returns (IPriceCapAdapter) { return new WstETHPriceCapAdapter( @@ -30,9 +28,7 @@ contract WstETHPriceCapAdapterTest is BaseTest { ratioProviderAddress, pairDescription, minimumSnapshotDelay, - snapshotRatio, - snapshotTimestamp, - maxYearlyRatioGrowthPercent + priceCapParams ); } @@ -43,7 +39,7 @@ contract WstETHPriceCapAdapterTest is BaseTest { uint16 maxYearlyRatioGrowthPercent ) public override returns (IPriceCapAdapter) { return - new WstETHPriceCapAdapter( + createAdapter( AaveV3Ethereum.ACL_MANAGER, BaseAggregatorsMainnet.ETH_USD_AGGREGATOR, MissingAssetsMainnet.STETH, @@ -66,7 +62,7 @@ contract WstETHPriceCapAdapterTest is BaseTest { // TODO: test that setParams func sets params as expected function test_cappedLatestAnswer() public { - WstETHPriceCapAdapter adapter = new WstETHPriceCapAdapter( + IPriceCapAdapter adapter = createAdapter( AaveV3Ethereum.ACL_MANAGER, BaseAggregatorsMainnet.ETH_USD_AGGREGATOR, MissingAssetsMainnet.STETH, @@ -87,7 +83,7 @@ contract WstETHPriceCapAdapterTest is BaseTest { } function test_updateParameters_cappedLatestAnswer() public { - WstETHPriceCapAdapter adapter = new WstETHPriceCapAdapter( + IPriceCapAdapter adapter = createAdapter( AaveV3Ethereum.ACL_MANAGER, BaseAggregatorsMainnet.ETH_USD_AGGREGATOR, MissingAssetsMainnet.STETH, @@ -107,7 +103,7 @@ contract WstETHPriceCapAdapterTest is BaseTest { ); vm.prank(AaveV3Ethereum.CAPS_PLUS_RISK_STEWARD); - adapter.setCapParameters(1151642955000000000, 1703743931, 20_00); + setCapParameters(adapter, 1151642955000000000, 1703743931, 20_00); price = adapter.latestAnswer(); @@ -123,7 +119,7 @@ contract WstETHPriceCapAdapterTest is BaseTest { uint48 snapshotTimestamp, uint16 maxYearlyRatioGrowthPercent ) public { - WstETHPriceCapAdapter adapter = new WstETHPriceCapAdapter( + IPriceCapAdapter adapter = createAdapter( AaveV3Ethereum.ACL_MANAGER, BaseAggregatorsMainnet.ETH_USD_AGGREGATOR, MissingAssetsMainnet.STETH, @@ -136,6 +132,6 @@ contract WstETHPriceCapAdapterTest is BaseTest { // TODO: fuzzing? vm.expectRevert(IPriceCapAdapter.CallerIsNotRiskOrPoolAdmin.selector); - adapter.setCapParameters(snapshotRatio, snapshotTimestamp, maxYearlyRatioGrowthPercent); + setCapParameters(adapter, snapshotRatio, snapshotTimestamp, maxYearlyRatioGrowthPercent); } }