Skip to content

Commit 2e91d4f

Browse files
committed
test: clean up; add more for new aggregator
1 parent 774ea78 commit 2e91d4f

File tree

1 file changed

+165
-74
lines changed

1 file changed

+165
-74
lines changed

tests/horizon/OracleDynamicBounds.t.sol

Lines changed: 165 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,32 @@
11
// SPDX-License-Identifier: BUSL-1.1
22
pragma solidity ^0.8.0;
33

4+
import {console2 as console} from 'forge-std/console2.sol';
5+
46
import {Test, Vm} from 'forge-std/Test.sol';
7+
import {IAaveOracle} from '../../src/contracts/interfaces/IAaveOracle.sol';
8+
import {IPool} from '../../src/contracts/interfaces/IPool.sol';
9+
import {AggregatorInterface} from '../../src/contracts/dependencies/chainlink/AggregatorInterface.sol';
10+
511
import {AaveV3HorizonEthereum} from './utils/AaveV3HorizonEthereum.sol';
612

713
/// forge-config: default.evm_version = "cancun"
814
contract OracleDynamicBoundsTest is Test {
9-
function setUp() public {
10-
vm.createSelectFork('mainnet', 23469081);
11-
}
15+
address constant USTB_NEW_AGGREGATOR = 0x267D0DD05fbc989565C521e0B8882f61027FF32A;
16+
address constant USCC_NEW_AGGREGATOR = 0x2d7Cd12f24bD28684847bF3e4317899a4Db53c58;
17+
address constant USYC_NEW_AGGREGATOR = 0x3C405e1FE8a6BE5d9b714B8C88Ad913F236B1639;
18+
address constant JTRSY_NEW_AGGREGATOR = 0xcf8683fFdFC4b871DF35D05bc763F239612e7272;
19+
address constant JAAA_NEW_AGGREGATOR = 0x3a8E8491236368a582b651786bEdA49BD5c3BA7B;
20+
address constant VBILL_NEW_AGGREGATOR = 0x04d81C346252E31Ee888393AF6E2037a9a4d70Af;
21+
22+
// read admin addresses found on-chain
23+
address constant USTB_READ_ADMIN = 0x47Fb2585D2C56Fe188D0E6ec628a38b74fCeeeDf;
24+
address constant USCC_READ_ADMIN = 0x69D55D504BC9556E377b340D19818E736bbB318b;
25+
address constant USYC_READ_ADMIN = 0x69D55D504BC9556E377b340D19818E736bbB318b;
26+
address constant JTRSY_READ_ADMIN = 0x47Fb2585D2C56Fe188D0E6ec628a38b74fCeeeDf;
27+
address constant JAAA_READ_ADMIN = 0x69D55D504BC9556E377b340D19818E736bbB318b;
28+
address constant VBILL_READ_ADMIN = 0x5ed77a9D9b7cc80E9d0D7711024AF38C2643C1c4;
29+
1230
struct ExpectedParams {
1331
uint64 maxExpectedApy;
1432
uint32 upperBoundTolerance;
@@ -20,6 +38,56 @@ contract OracleDynamicBoundsTest is Test {
2038
bool isActionTakingEnabled;
2139
}
2240

41+
struct NewAggregator {
42+
address aggregator;
43+
address readAdmin;
44+
}
45+
46+
mapping(address => ExpectedParams) internal expectedParams; // asset => expected params
47+
mapping(address => NewAggregator) internal newAggregators; // asset => new aggregator address
48+
49+
IAaveOracle internal oracle;
50+
function setUp() public {
51+
vm.createSelectFork('mainnet', 23469081);
52+
_initEnvironment();
53+
}
54+
55+
function _initEnvironment() internal {
56+
expectedParams[AaveV3HorizonEthereum.USTB_ADDRESS] = USTB_EXPECTED_PARAMS;
57+
expectedParams[AaveV3HorizonEthereum.USCC_ADDRESS] = USCC_EXPECTED_PARAMS;
58+
expectedParams[AaveV3HorizonEthereum.USYC_ADDRESS] = USYC_EXPECTED_PARAMS;
59+
expectedParams[AaveV3HorizonEthereum.JTRSY_ADDRESS] = JTRSY_EXPECTED_PARAMS;
60+
expectedParams[AaveV3HorizonEthereum.JAAA_ADDRESS] = JAAA_EXPECTED_PARAMS;
61+
expectedParams[AaveV3HorizonEthereum.VBILL_ADDRESS] = VBILL_EXPECTED_PARAMS;
62+
63+
newAggregators[AaveV3HorizonEthereum.USTB_ADDRESS] = NewAggregator({
64+
aggregator: USTB_NEW_AGGREGATOR,
65+
readAdmin: USTB_READ_ADMIN
66+
});
67+
newAggregators[AaveV3HorizonEthereum.USCC_ADDRESS] = NewAggregator({
68+
aggregator: USCC_NEW_AGGREGATOR,
69+
readAdmin: USCC_READ_ADMIN
70+
});
71+
newAggregators[AaveV3HorizonEthereum.USYC_ADDRESS] = NewAggregator({
72+
aggregator: USYC_NEW_AGGREGATOR,
73+
readAdmin: USYC_READ_ADMIN
74+
});
75+
newAggregators[AaveV3HorizonEthereum.JTRSY_ADDRESS] = NewAggregator({
76+
aggregator: JTRSY_NEW_AGGREGATOR,
77+
readAdmin: JTRSY_READ_ADMIN
78+
});
79+
newAggregators[AaveV3HorizonEthereum.JAAA_ADDRESS] = NewAggregator({
80+
aggregator: JAAA_NEW_AGGREGATOR,
81+
readAdmin: JAAA_READ_ADMIN
82+
});
83+
newAggregators[AaveV3HorizonEthereum.VBILL_ADDRESS] = NewAggregator({
84+
aggregator: VBILL_NEW_AGGREGATOR,
85+
readAdmin: VBILL_READ_ADMIN
86+
});
87+
88+
oracle = IAaveOracle(IPool(AaveV3HorizonEthereum.POOL).ADDRESSES_PROVIDER().getPriceOracle());
89+
}
90+
2391
ExpectedParams internal USTB_EXPECTED_PARAMS =
2492
ExpectedParams({
2593
maxExpectedApy: 415,
@@ -103,67 +171,44 @@ contract OracleDynamicBoundsTest is Test {
103171
assertEq(updater, AaveV3HorizonEthereum.HORIZON_OPS, 'updater');
104172
}
105173

106-
function test_ustb_oracle() external {
107-
test_horizon_adapter(
108-
AaveV3HorizonEthereum.USTB_ADDRESS,
109-
AaveV3HorizonEthereum.USTB_PRICE_FEED_ADAPTER,
110-
true
111-
);
112-
test_registry_params(AaveV3HorizonEthereum.USTB_ADDRESS, USTB_EXPECTED_PARAMS);
113-
test_lookback_data(AaveV3HorizonEthereum.USTB_ADDRESS);
174+
function test_ustb() external {
175+
address oracleSource = oracle.getSourceOfAsset(AaveV3HorizonEthereum.USTB_ADDRESS);
176+
test_asset(AaveV3HorizonEthereum.USTB_ADDRESS, oracleSource, true);
114177
}
115178

116-
function test_uscc_oracle() external {
117-
test_horizon_adapter(
118-
AaveV3HorizonEthereum.USCC_ADDRESS,
119-
AaveV3HorizonEthereum.USCC_PRICE_FEED_ADAPTER,
120-
true
121-
);
122-
test_registry_params(AaveV3HorizonEthereum.USCC_ADDRESS, USCC_EXPECTED_PARAMS);
123-
test_lookback_data(AaveV3HorizonEthereum.USCC_ADDRESS);
179+
function test_uscc() external {
180+
address oracleSource = oracle.getSourceOfAsset(AaveV3HorizonEthereum.USCC_ADDRESS);
181+
test_asset(AaveV3HorizonEthereum.USCC_ADDRESS, oracleSource, true);
124182
}
125183

126-
function test_usyc_oracle() external {
127-
test_horizon_adapter(
128-
AaveV3HorizonEthereum.USYC_ADDRESS,
129-
AaveV3HorizonEthereum.USYC_PRICE_FEED,
130-
false
131-
);
132-
test_registry_params(AaveV3HorizonEthereum.USYC_ADDRESS, USYC_EXPECTED_PARAMS);
133-
test_lookback_data(AaveV3HorizonEthereum.USYC_ADDRESS);
184+
function test_usyc() external {
185+
address oracleSource = oracle.getSourceOfAsset(AaveV3HorizonEthereum.USYC_ADDRESS);
186+
test_asset(AaveV3HorizonEthereum.USYC_ADDRESS, oracleSource, false);
134187
}
135188

136-
function test_jtrsy_oracle() external {
137-
test_horizon_adapter(
138-
AaveV3HorizonEthereum.JTRSY_ADDRESS,
139-
AaveV3HorizonEthereum.JTRSY_PRICE_FEED_ADAPTER,
140-
true
141-
);
142-
test_registry_params(AaveV3HorizonEthereum.JTRSY_ADDRESS, JTRSY_EXPECTED_PARAMS);
143-
test_lookback_data(AaveV3HorizonEthereum.JTRSY_ADDRESS);
189+
function test_jtrsy() external {
190+
address oracleSource = oracle.getSourceOfAsset(AaveV3HorizonEthereum.JTRSY_ADDRESS);
191+
test_asset(AaveV3HorizonEthereum.JTRSY_ADDRESS, oracleSource, true);
144192
}
145193

146-
function test_jaaa_oracle() external {
147-
test_horizon_adapter(
148-
AaveV3HorizonEthereum.JAAA_ADDRESS,
149-
AaveV3HorizonEthereum.JAAA_PRICE_FEED_ADAPTER,
150-
true
151-
);
152-
test_registry_params(AaveV3HorizonEthereum.JAAA_ADDRESS, JAAA_EXPECTED_PARAMS);
153-
test_lookback_data(AaveV3HorizonEthereum.JAAA_ADDRESS);
194+
function test_jaaa() external {
195+
address oracleSource = oracle.getSourceOfAsset(AaveV3HorizonEthereum.JAAA_ADDRESS);
196+
test_asset(AaveV3HorizonEthereum.JAAA_ADDRESS, oracleSource, true);
154197
}
155198

156199
function test_vbill() external {
157-
test_horizon_adapter(
158-
AaveV3HorizonEthereum.VBILL_ADDRESS,
159-
AaveV3HorizonEthereum.VBILL_PRICE_FEED,
160-
false
161-
);
162-
test_registry_params(AaveV3HorizonEthereum.VBILL_ADDRESS, VBILL_EXPECTED_PARAMS);
163-
test_lookback_data(AaveV3HorizonEthereum.VBILL_ADDRESS);
200+
// VBILL not deployed yet, get price feed directly from lib
201+
test_asset(AaveV3HorizonEthereum.VBILL_ADDRESS, AaveV3HorizonEthereum.VBILL_PRICE_FEED, false);
164202
}
165203

166-
function test_registry_params(address asset, ExpectedParams memory expectedParams) internal {
204+
function test_asset(address asset, address oracleSource, bool isAdapter) internal {
205+
test_horizon_adapter(asset, oracleSource, isAdapter);
206+
test_registry_params(asset);
207+
test_lookback_data(asset);
208+
test_new_aggregator(asset);
209+
}
210+
211+
function test_registry_params(address asset) internal {
167212
bool success;
168213
bytes memory data;
169214

@@ -179,6 +224,8 @@ contract OracleDynamicBoundsTest is Test {
179224
);
180225
require(success, 'Failed to call getParametersForAsset()');
181226

227+
ExpectedParams memory expectedParam = expectedParams[asset];
228+
182229
(
183230
uint64 maxExpectedApy,
184231
uint32 upperBoundTolerance,
@@ -190,36 +237,31 @@ contract OracleDynamicBoundsTest is Test {
190237
bool isActionTakingEnabled
191238
) = abi.decode(data, (uint64, uint32, uint32, uint32, uint80, bool, bool, bool));
192239

193-
assertEq(maxExpectedApy, expectedParams.maxExpectedApy, 'maxExpectedApy');
194-
assertEq(upperBoundTolerance, expectedParams.upperBoundTolerance, 'upperBoundTolerance');
195-
assertEq(lowerBoundTolerance, expectedParams.lowerBoundTolerance, 'lowerBoundTolerance');
196-
assertEq(maxDiscount, expectedParams.maxDiscount, 'maxDiscount');
197-
assertEq(lookbackWindowSize, expectedParams.lookbackWindowSize, 'lookbackWindowSize');
198-
assertEq(isUpperBoundEnabled, expectedParams.isUpperBoundEnabled, 'isUpperBoundEnabled');
199-
assertEq(isLowerBoundEnabled, expectedParams.isLowerBoundEnabled, 'isLowerBoundEnabled');
200-
assertEq(isActionTakingEnabled, expectedParams.isActionTakingEnabled, 'isActionTakingEnabled');
240+
assertEq(maxExpectedApy, expectedParam.maxExpectedApy, 'maxExpectedApy');
241+
assertEq(upperBoundTolerance, expectedParam.upperBoundTolerance, 'upperBoundTolerance');
242+
assertEq(lowerBoundTolerance, expectedParam.lowerBoundTolerance, 'lowerBoundTolerance');
243+
assertEq(maxDiscount, expectedParam.maxDiscount, 'maxDiscount');
244+
assertEq(lookbackWindowSize, expectedParam.lookbackWindowSize, 'lookbackWindowSize');
245+
assertEq(isUpperBoundEnabled, expectedParam.isUpperBoundEnabled, 'isUpperBoundEnabled');
246+
assertEq(isLowerBoundEnabled, expectedParam.isLowerBoundEnabled, 'isLowerBoundEnabled');
247+
assertEq(isActionTakingEnabled, expectedParam.isActionTakingEnabled, 'isActionTakingEnabled');
201248
}
202249

203-
function test_horizon_adapter(address asset, address source, bool isAdapter) internal {
250+
/// test that the oracle source from horizon adapter/oracle source is the same as the oracle address from the param registry
251+
function test_horizon_adapter(address asset, address oracleSource, bool isAdapter) internal {
204252
bool success;
205253
bytes memory data;
206254
if (isAdapter) {
207-
// oracle source from horizon adapter
208-
(success, data) = source.call(abi.encodeWithSignature('source()'));
255+
// if adapter, get oracle source from horizon adapter source
256+
(success, data) = oracleSource.call(abi.encodeWithSignature('source()'));
209257
require(success, 'Failed to call source()');
210-
source = abi.decode(data, (address));
258+
oracleSource = abi.decode(data, (address));
211259
}
212-
213-
// oracle address from param registry
214-
(success, data) = AaveV3HorizonEthereum.PARAM_REGISTRY.call(
215-
abi.encodeWithSignature('getOracle(address)', asset)
216-
);
217-
require(success, 'Failed to call getOracle()');
218-
address oracle = abi.decode(data, (address));
219-
220-
assertEq(source, oracle, 'source');
260+
address oracle = _getParamRegistryOracle(asset);
261+
assertEq(oracleSource, oracle, 'source');
221262
}
222263

264+
// read look back data from param registry
223265
function test_lookback_data(address asset) internal {
224266
bool success;
225267
bytes memory data;
@@ -229,6 +271,7 @@ contract OracleDynamicBoundsTest is Test {
229271
);
230272
require(success, 'Failed to call getLookbackData()');
231273

274+
// reads from old aggregator data
232275
(
233276
uint80 roundId,
234277
int256 answer,
@@ -239,8 +282,56 @@ contract OracleDynamicBoundsTest is Test {
239282

240283
assertGt(roundId, 0, 'roundId');
241284
assertGt(answer, 0, 'answer');
242-
assertApproxEqRel(startedAt, vm.getBlockTimestamp() - 4 * 1 days, 1e14, 'startedAt');
243-
assertApproxEqRel(updatedAt, vm.getBlockTimestamp() - 4 * 1 days, 1e14, 'updatedAt');
285+
assertApproxEqRel(
286+
startedAt,
287+
vm.getBlockTimestamp() - expectedParams[asset].lookbackWindowSize * 1 days, // within expected lookback window
288+
1e15,
289+
'startedAt'
290+
);
291+
assertApproxEqRel(
292+
updatedAt,
293+
vm.getBlockTimestamp() - expectedParams[asset].lookbackWindowSize * 1 days, // within expected lookback window
294+
1e15,
295+
'updatedAt'
296+
);
244297
assertGt(answeredInRound, 0, 'answeredInRound');
245298
}
299+
300+
function test_new_aggregator(address asset) internal {
301+
// new aggregator data
302+
303+
vm.prank(newAggregators[asset].readAdmin); // has access to price feed
304+
(
305+
uint80 roundId,
306+
int256 answer,
307+
uint256 startedAt,
308+
uint256 updatedAt,
309+
uint80 answeredInRound
310+
) = AggregatorInterface(newAggregators[asset].aggregator).latestRoundData();
311+
312+
assertGt(roundId, expectedParams[asset].lookbackWindowSize, 'roundId');
313+
assertGt(answer, 0, 'answer');
314+
assertApproxEqRel(
315+
startedAt,
316+
vm.getBlockTimestamp() - expectedParams[asset].lookbackWindowSize * 1 days, // within expected lookback window
317+
1e15,
318+
'startedAt'
319+
);
320+
assertApproxEqRel(
321+
updatedAt,
322+
vm.getBlockTimestamp() - expectedParams[asset].lookbackWindowSize * 1 days, // within expected lookback window
323+
1e15,
324+
'updatedAt'
325+
);
326+
assertGt(answeredInRound, expectedParams[asset].lookbackWindowSize, 'answeredInRound');
327+
}
328+
329+
// read oracle address from param registry
330+
function _getParamRegistryOracle(address asset) internal returns (address) {
331+
(bool success, bytes memory data) = AaveV3HorizonEthereum.PARAM_REGISTRY.call(
332+
abi.encodeWithSignature('getOracle(address)', asset)
333+
);
334+
require(success, 'Failed to call getOracle()');
335+
return abi.decode(data, (address));
336+
}
246337
}

0 commit comments

Comments
 (0)