@@ -5,6 +5,7 @@ import {IAaveOracle} from 'aave-v3-origin/contracts/interfaces/IAaveOracle.sol';
55import {ProtocolV3HorizonTestBase, ReserveConfig} from 'tests/utils/ProtocolV3HorizonTestBase.sol ' ;
66import {AaveV3EthereumHorizon, AaveV3EthereumHorizonAssets} from 'aave-address-book-latest/AaveV3EthereumHorizon.sol ' ;
77import {AaveV3Ethereum, AaveV3EthereumAssets} from 'aave-address-book-latest/AaveV3Ethereum.sol ' ;
8+ import {IPriceCapAdapterStable} from 'src/interfaces/IPriceCapAdapterStable.sol ' ;
89import {AaveV3Horizon_PriceFeed_20260404} from './AaveV3Horizon_PriceFeed_20260404.sol ' ;
910
1011/**
@@ -17,12 +18,24 @@ contract AaveV3Horizon_PriceFeed_20260404_Test is ProtocolV3HorizonTestBase {
1718 address internal constant OLD_RLUSD_ORACLE = AaveV3EthereumHorizonAssets.RLUSD_ORACLE;
1819 address internal constant OLD_USDC_ORACLE = AaveV3EthereumHorizonAssets.USDC_ORACLE;
1920
20- address internal constant NEW_RLUSD_ORACLE = 0x9E7c31e9b3C76Ea759D9f7464210353862F0c957 ; // stable cap adapter
21- address internal constant NEW_USDC_ORACLE = 0x46f94aff8cF7DdC8557eF69f7276087b01C8f363 ; // stable cap adapter
21+ address internal newRlusdOracle; // stable cap adapter
22+ address internal newUsdcOracle; // stable cap adapter
23+
24+ IPriceCapAdapterStable internal rlusdAdapter;
25+ IPriceCapAdapterStable internal usdcAdapter;
26+
27+ /// 10200 bps expressed in the 8-decimal feed precision used by the adapter.
28+ int256 internal constant EXPECTED_PRICE_CAP = int256 (10200 ) * 1e4 ;
2229
2330 function setUp () public {
2431 vm.createSelectFork (vm.rpcUrl ('mainnet ' ), 24852499 );
2532 proposal = new AaveV3Horizon_PriceFeed_20260404 ();
33+
34+ newRlusdOracle = proposal.NEW_RLUSD_ORACLE ();
35+ newUsdcOracle = proposal.NEW_USDC_ORACLE ();
36+
37+ rlusdAdapter = IPriceCapAdapterStable (newRlusdOracle);
38+ usdcAdapter = IPriceCapAdapterStable (newUsdcOracle);
2639 }
2740
2841 /**
@@ -32,8 +45,11 @@ contract AaveV3Horizon_PriceFeed_20260404_Test is ProtocolV3HorizonTestBase {
3245 defaultTest_v3_3 ('AaveV3Horizon_PriceFeed_20260404 ' , _pool (), _executePayload);
3346 }
3447
48+ /// 1 BPS = 0.01% expressed in 1e18 precision
49+ uint256 internal constant ONE_BPS = 1e14 ;
50+
3551 /**
36- * @dev Verify the RLUSD oracle is updated to the CAPO adapter.
52+ * @dev Verify the RLUSD oracle is updated to the cap adapter.
3753 */
3854 function test_RLUSD_PriceFeedUpdate () public {
3955 IAaveOracle oracle = IAaveOracle (AaveV3EthereumHorizon.ORACLE);
@@ -46,17 +62,23 @@ contract AaveV3Horizon_PriceFeed_20260404_Test is ProtocolV3HorizonTestBase {
4662 AaveV3EthereumAssets.RLUSD_ORACLE,
4763 'RLUSD oracle should differ from V3 core before '
4864 );
65+ uint256 priceBefore = oracle.getAssetPrice (RLUSD);
4966
5067 _executePayload ();
5168
5269 // AFTER
53- assertEq (oracle.getSourceOfAsset (RLUSD), NEW_RLUSD_ORACLE, 'RLUSD oracle after ' );
54- uint256 price = oracle.getAssetPrice (RLUSD);
55- assertGt (price, 0 , 'RLUSD price must be positive ' );
70+ assertEq (oracle.getSourceOfAsset (RLUSD), newRlusdOracle, 'RLUSD oracle after ' );
71+ uint256 priceAfter = oracle.getAssetPrice (RLUSD);
72+ assertApproxEqRel (
73+ priceAfter,
74+ priceBefore,
75+ ONE_BPS,
76+ 'RLUSD price must be within 1 BPS of prior '
77+ );
5678 }
5779
5880 /**
59- * @dev Verify the USDC oracle is updated to the CAPO adapter.
81+ * @dev Verify the USDC oracle is updated to the cap adapter.
6082 */
6183 function test_USDC_PriceFeedUpdate () public {
6284 IAaveOracle oracle = IAaveOracle (AaveV3EthereumHorizon.ORACLE);
@@ -65,16 +87,17 @@ contract AaveV3Horizon_PriceFeed_20260404_Test is ProtocolV3HorizonTestBase {
6587 // BEFORE
6688 assertEq (oracle.getSourceOfAsset (USDC), OLD_USDC_ORACLE, 'USDC oracle before ' );
6789 assertTrue (
68- oracle.getSourceOfAsset (USDC) != NEW_USDC_ORACLE ,
90+ oracle.getSourceOfAsset (USDC) != newUsdcOracle ,
6991 'USDC oracle should differ from V3 core before '
7092 );
93+ uint256 priceBefore = oracle.getAssetPrice (USDC);
7194
7295 _executePayload ();
7396
7497 // AFTER
75- assertEq (oracle.getSourceOfAsset (USDC), NEW_USDC_ORACLE , 'USDC oracle after ' );
76- uint256 price = oracle.getAssetPrice (USDC);
77- assertGt (price, 0 , 'USDC price must be positive ' );
98+ assertEq (oracle.getSourceOfAsset (USDC), newUsdcOracle , 'USDC oracle after ' );
99+ uint256 priceAfter = oracle.getAssetPrice (USDC);
100+ assertApproxEqRel (priceAfter, priceBefore, ONE_BPS, 'USDC price must be within 1 BPS of prior ' );
78101 }
79102
80103 /// @dev Verify GHO oracle already matches V3 core (only other stablecoin within both pools).
@@ -87,18 +110,48 @@ contract AaveV3Horizon_PriceFeed_20260404_Test is ProtocolV3HorizonTestBase {
87110 );
88111 }
89112
90- /// @dev Override expected price feeds so the snapshot validator accepts the new oracles.
91- function _expectedPriceFeed (address underlying ) internal pure override returns (address ) {
113+ /// @dev RLUSD stable cap adapter constructor params.
114+ function test_RLUSD_AdapterParams () public view {
115+ assertEq (
116+ rlusdAdapter.ACL_MANAGER (),
117+ address (AaveV3EthereumHorizon.ACL_MANAGER),
118+ 'RLUSD adapter ACL_MANAGER mismatch '
119+ );
120+ assertEq (
121+ rlusdAdapter.ASSET_TO_USD_AGGREGATOR (),
122+ AaveV3EthereumHorizonAssets.RLUSD_ORACLE,
123+ 'RLUSD adapter underlying must be Horizon non-SVR Chainlink feed '
124+ );
125+ assertEq (rlusdAdapter.getPriceCap (), EXPECTED_PRICE_CAP, 'RLUSD adapter price cap mismatch ' );
126+ }
127+
128+ /// @dev USDC stable cap adapter constructor params.
129+ function test_USDC_AdapterParams () public view {
130+ assertEq (
131+ usdcAdapter.ACL_MANAGER (),
132+ address (AaveV3EthereumHorizon.ACL_MANAGER),
133+ 'USDC adapter ACL_MANAGER mismatch '
134+ );
135+ assertEq (
136+ usdcAdapter.ASSET_TO_USD_AGGREGATOR (),
137+ AaveV3EthereumHorizonAssets.USDC_ORACLE,
138+ 'USDC adapter underlying must be Horizon non-SVR Chainlink feed '
139+ );
140+ assertEq (usdcAdapter.getPriceCap (), EXPECTED_PRICE_CAP, 'USDC adapter price cap mismatch ' );
141+ }
142+
143+ function _executePayload () internal {
144+ _executeHorizonPayload (address (proposal));
145+ }
146+
147+ /// @dev Override expected price feeds so the snapshot validator in defaultTest accepts the new oracles.
148+ function _expectedPriceFeed (address underlying ) internal override returns (address ) {
92149 if (underlying == AaveV3EthereumHorizonAssets.RLUSD_UNDERLYING) {
93- return NEW_RLUSD_ORACLE ;
150+ return newRlusdOracle ;
94151 }
95152 if (underlying == AaveV3EthereumHorizonAssets.USDC_UNDERLYING) {
96- return NEW_USDC_ORACLE ;
153+ return newUsdcOracle ;
97154 }
98155 return super ._expectedPriceFeed (underlying);
99156 }
100-
101- function _executePayload () internal {
102- _executeHorizonPayload (address (proposal));
103- }
104157}
0 commit comments