Skip to content

Commit 05365e3

Browse files
committed
fix: assert custom asset price is less than the price cap
1 parent 2770a57 commit 05365e3

File tree

4 files changed

+312
-1
lines changed

4 files changed

+312
-1
lines changed

aave-core/aave-config/sources/error_config.move

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,8 @@ module aave_config::error_config {
255255
const EINVALID_SNAPSHOT_RATIO: u64 = 1227;
256256
/// The snapshot timestamp is invalid
257257
const EINVALID_SNAPSHOT_TIMESTAMP: u64 = 1228;
258+
/// The assigned custom price is above the price cap
259+
const ECUSTOM_PRICE_ABOVE_PRICE_CAP: u64 = 1229;
258260

259261
// aave_rate module error code range from 1301 to 1400.
260262
/// @notice Account is not the rate's owner
@@ -859,6 +861,12 @@ module aave_config::error_config {
859861
EINVALID_SNAPSHOT_TIMESTAMP
860862
}
861863

864+
/// @notice Returns the error code for custom price above price cap
865+
/// @return Error code as u64
866+
public fun get_ecustom_price_above_price_cap(): u64 {
867+
ECUSTOM_PRICE_ABOVE_PRICE_CAP
868+
}
869+
862870
/// @notice Returns the error code for invalid optimal usage ratio
863871
/// @return Error code as u64
864872
public fun get_einvalid_optimal_usage_ratio(): u64 {

aave-core/aave-config/tests/error_tests.move

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,8 @@ module aave_config::error_tests {
169169
get_einvalid_growth_rate,
170170
get_einvalid_snapshot_delay,
171171
get_einvalid_snapshot_ratio,
172-
get_einvalid_snapshot_timestamp
172+
get_einvalid_snapshot_timestamp,
173+
get_ecustom_price_above_price_cap
173174
};
174175

175176
const TEST_SUCCESS: u64 = 1;
@@ -438,6 +439,8 @@ module aave_config::error_tests {
438439
const EINVALID_SNAPSHOT_RATIO: u64 = 1227;
439440
/// The snapshot timestamp is invalid
440441
const EINVALID_SNAPSHOT_TIMESTAMP: u64 = 1228;
442+
/// The assigned custom price is above the price cap
443+
const ECUSTOM_PRICE_ABOVE_PRICE_CAP: u64 = 1229;
441444

442445
// aave_rate module error code range from 1301 to 1400.
443446

@@ -1314,6 +1317,14 @@ module aave_config::error_tests {
13141317
);
13151318
}
13161319

1320+
#[test]
1321+
public fun test_ecustom_price_above_price_cap() {
1322+
assert!(
1323+
get_ecustom_price_above_price_cap() == ECUSTOM_PRICE_ABOVE_PRICE_CAP,
1324+
TEST_SUCCESS
1325+
);
1326+
}
1327+
13171328
#[test]
13181329
public fun test_get_einvalid_ratio_timestamp() {
13191330
assert!(get_einvalid_ratio_timestamp() == EINVALID_RATIO_TIMESTAMP, TEST_SUCCESS);

aave-core/aave-oracle/sources/oracle.move

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -559,6 +559,13 @@ module aave_oracle::oracle {
559559
) acquires PriceOracleData {
560560
only_asset_listing_or_pool_admin(account);
561561
assert!(custom_price > 0, error_config::get_ezero_asset_custom_price());
562+
if (is_asset_price_capped(asset)) {
563+
let (capped_price, _) = get_asset_price_and_timestamp(asset);
564+
assert!(
565+
custom_price <= capped_price,
566+
error_config::get_ecustom_price_above_price_cap()
567+
);
568+
};
562569
update_asset_custom_price(asset, custom_price);
563570
}
564571

aave-core/aave-oracle/tests/oracle_tests.move

Lines changed: 285 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -984,6 +984,291 @@ module aave_oracle::oracle_tests {
984984
);
985985
}
986986

987+
#[
988+
test(
989+
super_admin = @aave_acl,
990+
oracle_admin = @0x06,
991+
aave_oracle = @aave_oracle,
992+
data_feeds = @data_feeds,
993+
platform = @platform,
994+
aptos = @aptos_framework
995+
)
996+
]
997+
fun test_oracle_set_stable_price_cap_adapter_success(
998+
super_admin: &signer,
999+
oracle_admin: &signer,
1000+
aave_oracle: &signer,
1001+
data_feeds: &signer,
1002+
platform: &signer,
1003+
aptos: &signer
1004+
) {
1005+
// start the timer
1006+
set_time_has_started_for_testing(aptos);
1007+
1008+
// init the acl module
1009+
acl_manage::test_init_module(super_admin);
1010+
1011+
// add the roles for the oracle admin
1012+
acl_manage::add_pool_admin(super_admin, signer::address_of(oracle_admin));
1013+
assert!(
1014+
acl_manage::is_pool_admin(signer::address_of(oracle_admin)), TEST_SUCCESS
1015+
);
1016+
acl_manage::add_asset_listing_admin(
1017+
super_admin, signer::address_of(oracle_admin)
1018+
);
1019+
assert!(
1020+
acl_manage::is_asset_listing_admin(signer::address_of(oracle_admin)),
1021+
TEST_SUCCESS
1022+
);
1023+
1024+
// init aave oracle
1025+
config_oracle(aave_oracle, data_feeds, platform);
1026+
1027+
// define asset and price cap
1028+
let asset_address = @0x0;
1029+
let asset_capped_price = 2 * TEST_FEED_PRICE;
1030+
1031+
// first set the CL feed for the asset
1032+
oracle::set_asset_feed_id(oracle_admin, asset_address, TEST_FEED_ID);
1033+
1034+
// set asset price cap (that succeeds because the cap is 2 * price asset)
1035+
oracle::set_price_cap_stable_adapter(
1036+
oracle_admin,
1037+
asset_address,
1038+
asset_capped_price
1039+
);
1040+
1041+
// check for specific events
1042+
let emitted_events = emitted_events<oracle::PriceCapUpdated>();
1043+
assert!(
1044+
vector::length(&emitted_events) == 1,
1045+
TEST_SUCCESS
1046+
);
1047+
1048+
// the asset price cap must be retrievable
1049+
assert!(
1050+
*option::borrow(&oracle::get_stable_price_cap(asset_address))
1051+
== asset_capped_price,
1052+
TEST_SUCCESS
1053+
);
1054+
1055+
// now simulate an increase of the price higher than the cap, i.e. price must be capped
1056+
let current_time = timestamp::now_seconds();
1057+
let fresh_timestamp = (current_time * 1000) as u256;
1058+
let new_increased_price = asset_capped_price + 1;
1059+
registry::perform_update_for_test(
1060+
TEST_FEED_ID,
1061+
fresh_timestamp,
1062+
new_increased_price,
1063+
vector::empty<u8>()
1064+
);
1065+
1066+
// asset is capped at this point
1067+
assert!(oracle::is_asset_price_capped(asset_address), TEST_SUCCESS);
1068+
1069+
// check the asset price
1070+
assert!(
1071+
oracle::get_asset_price(asset_address) == asset_capped_price,
1072+
TEST_SUCCESS
1073+
);
1074+
}
1075+
1076+
#[
1077+
test(
1078+
super_admin = @aave_acl,
1079+
oracle_admin = @0x06,
1080+
aave_oracle = @aave_oracle,
1081+
data_feeds = @data_feeds,
1082+
platform = @platform,
1083+
aptos = @aptos_framework
1084+
)
1085+
]
1086+
#[expected_failure(abort_code = 1229, location = aave_oracle::oracle)]
1087+
fun test_oracle_stable_price_cap_adapter_when_custom_price_higher_than_price_cap(
1088+
super_admin: &signer,
1089+
oracle_admin: &signer,
1090+
aave_oracle: &signer,
1091+
data_feeds: &signer,
1092+
platform: &signer,
1093+
aptos: &signer
1094+
) {
1095+
// start the timer
1096+
set_time_has_started_for_testing(aptos);
1097+
1098+
// init the acl module
1099+
acl_manage::test_init_module(super_admin);
1100+
1101+
// add the roles for the oracle admin
1102+
acl_manage::add_pool_admin(super_admin, signer::address_of(oracle_admin));
1103+
assert!(
1104+
acl_manage::is_pool_admin(signer::address_of(oracle_admin)), TEST_SUCCESS
1105+
);
1106+
acl_manage::add_asset_listing_admin(
1107+
super_admin, signer::address_of(oracle_admin)
1108+
);
1109+
assert!(
1110+
acl_manage::is_asset_listing_admin(signer::address_of(oracle_admin)),
1111+
TEST_SUCCESS
1112+
);
1113+
1114+
// init aave oracle
1115+
config_oracle(aave_oracle, data_feeds, platform);
1116+
1117+
// define asset and price cap
1118+
let asset_address = @0x0;
1119+
let asset_capped_price = 2 * TEST_FEED_PRICE;
1120+
1121+
// first set the CL feed for the asset
1122+
oracle::set_asset_feed_id(oracle_admin, asset_address, TEST_FEED_ID);
1123+
1124+
// set asset price cap (that succeeds because the cap is 2 * price asset)
1125+
oracle::set_price_cap_stable_adapter(
1126+
oracle_admin,
1127+
asset_address,
1128+
asset_capped_price
1129+
);
1130+
1131+
// check for specific events
1132+
let emitted_events = emitted_events<oracle::PriceCapUpdated>();
1133+
assert!(
1134+
vector::length(&emitted_events) == 1,
1135+
TEST_SUCCESS
1136+
);
1137+
1138+
// the asset price cap must be retrievable
1139+
assert!(
1140+
*option::borrow(&oracle::get_stable_price_cap(asset_address))
1141+
== asset_capped_price,
1142+
TEST_SUCCESS
1143+
);
1144+
1145+
// now simulate an increase of the price higher than the cap, i.e. price must be capped
1146+
let current_time = timestamp::now_seconds();
1147+
let fresh_timestamp = (current_time * 1000) as u256;
1148+
let new_increased_price = asset_capped_price + 1;
1149+
registry::perform_update_for_test(
1150+
TEST_FEED_ID,
1151+
fresh_timestamp,
1152+
new_increased_price,
1153+
vector::empty<u8>()
1154+
);
1155+
1156+
// asset is capped at this point
1157+
assert!(oracle::is_asset_price_capped(asset_address), TEST_SUCCESS);
1158+
1159+
// check the asset price
1160+
assert!(
1161+
oracle::get_asset_price(asset_address) == asset_capped_price,
1162+
TEST_SUCCESS
1163+
);
1164+
1165+
// try and set a custom price higher than the price cap
1166+
let new_custom_price = asset_capped_price + 1;
1167+
oracle::set_asset_custom_price(oracle_admin, asset_address, new_custom_price);
1168+
}
1169+
1170+
#[
1171+
test(
1172+
super_admin = @aave_acl,
1173+
oracle_admin = @0x06,
1174+
aave_oracle = @aave_oracle,
1175+
data_feeds = @data_feeds,
1176+
platform = @platform,
1177+
aptos = @aptos_framework
1178+
)
1179+
]
1180+
fun test_oracle_stable_price_cap_adapter_when_custom_price_lower_than_price_cap(
1181+
super_admin: &signer,
1182+
oracle_admin: &signer,
1183+
aave_oracle: &signer,
1184+
data_feeds: &signer,
1185+
platform: &signer,
1186+
aptos: &signer
1187+
) {
1188+
// start the timer
1189+
set_time_has_started_for_testing(aptos);
1190+
1191+
// init the acl module
1192+
acl_manage::test_init_module(super_admin);
1193+
1194+
// add the roles for the oracle admin
1195+
acl_manage::add_pool_admin(super_admin, signer::address_of(oracle_admin));
1196+
assert!(
1197+
acl_manage::is_pool_admin(signer::address_of(oracle_admin)), TEST_SUCCESS
1198+
);
1199+
acl_manage::add_asset_listing_admin(
1200+
super_admin, signer::address_of(oracle_admin)
1201+
);
1202+
assert!(
1203+
acl_manage::is_asset_listing_admin(signer::address_of(oracle_admin)),
1204+
TEST_SUCCESS
1205+
);
1206+
1207+
// init aave oracle
1208+
config_oracle(aave_oracle, data_feeds, platform);
1209+
1210+
// define asset and price cap
1211+
let asset_address = @0x0;
1212+
let asset_capped_price = 2 * TEST_FEED_PRICE;
1213+
1214+
// first set the CL feed for the asset
1215+
oracle::set_asset_feed_id(oracle_admin, asset_address, TEST_FEED_ID);
1216+
1217+
// set asset price cap (that succeeds because the cap is 2 * price asset)
1218+
oracle::set_price_cap_stable_adapter(
1219+
oracle_admin,
1220+
asset_address,
1221+
asset_capped_price
1222+
);
1223+
1224+
// check for specific events
1225+
let emitted_events = emitted_events<oracle::PriceCapUpdated>();
1226+
assert!(
1227+
vector::length(&emitted_events) == 1,
1228+
TEST_SUCCESS
1229+
);
1230+
1231+
// the asset price cap must be retrievable
1232+
assert!(
1233+
*option::borrow(&oracle::get_stable_price_cap(asset_address))
1234+
== asset_capped_price,
1235+
TEST_SUCCESS
1236+
);
1237+
1238+
// now simulate an increase of the price higher than the cap, i.e. price must be capped
1239+
let current_time = timestamp::now_seconds();
1240+
let fresh_timestamp = (current_time * 1000) as u256;
1241+
let new_increased_price = asset_capped_price + 1;
1242+
registry::perform_update_for_test(
1243+
TEST_FEED_ID,
1244+
fresh_timestamp,
1245+
new_increased_price,
1246+
vector::empty<u8>()
1247+
);
1248+
1249+
// asset is capped at this point
1250+
assert!(oracle::is_asset_price_capped(asset_address), TEST_SUCCESS);
1251+
1252+
// check the asset price
1253+
assert!(
1254+
oracle::get_asset_price(asset_address) == asset_capped_price,
1255+
TEST_SUCCESS
1256+
);
1257+
1258+
// try and set a custom price lower than the price cap
1259+
let new_custom_price = asset_capped_price - 1;
1260+
oracle::set_asset_custom_price(oracle_admin, asset_address, new_custom_price);
1261+
1262+
// check the asset price - must be the new custom price
1263+
assert!(
1264+
oracle::get_asset_price(asset_address) == new_custom_price,
1265+
TEST_SUCCESS
1266+
);
1267+
1268+
// asset is no longer capped at this point
1269+
assert!(!oracle::is_asset_price_capped(asset_address), TEST_SUCCESS);
1270+
}
1271+
9871272
#[
9881273
test(
9891274
super_admin = @aave_acl,

0 commit comments

Comments
 (0)