Skip to content

Commit 233c96b

Browse files
committed
test: assertions on price comparison; cap adapter params
1 parent 19658f9 commit 233c96b

2 files changed

Lines changed: 80 additions & 19 deletions

File tree

src/AaveV3Horizon_PriceFeed_20260404/AaveV3Horizon_PriceFeed_20260404.t.sol

Lines changed: 72 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import {IAaveOracle} from 'aave-v3-origin/contracts/interfaces/IAaveOracle.sol';
55
import {ProtocolV3HorizonTestBase, ReserveConfig} from 'tests/utils/ProtocolV3HorizonTestBase.sol';
66
import {AaveV3EthereumHorizon, AaveV3EthereumHorizonAssets} from 'aave-address-book-latest/AaveV3EthereumHorizon.sol';
77
import {AaveV3Ethereum, AaveV3EthereumAssets} from 'aave-address-book-latest/AaveV3Ethereum.sol';
8+
import {IPriceCapAdapterStable} from 'src/interfaces/IPriceCapAdapterStable.sol';
89
import {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
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// SPDX-License-Identifier: MIT
2+
pragma solidity ^0.8.0;
3+
4+
interface IPriceCapAdapterStable {
5+
function ACL_MANAGER() external view returns (address);
6+
function ASSET_TO_USD_AGGREGATOR() external view returns (address);
7+
function getPriceCap() external view returns (int256);
8+
}

0 commit comments

Comments
 (0)