Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions aave-core/aave-config/sources/error_config.move
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,8 @@ module aave_config::error_config {
const EINVALID_SNAPSHOT_RATIO: u64 = 1227;
/// The snapshot timestamp is invalid
const EINVALID_SNAPSHOT_TIMESTAMP: u64 = 1228;
/// The assigned custom price is above the price cap
const ECUSTOM_PRICE_ABOVE_PRICE_CAP: u64 = 1229;

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

/// @notice Returns the error code for custom price above price cap
/// @return Error code as u64
public fun get_ecustom_price_above_price_cap(): u64 {
ECUSTOM_PRICE_ABOVE_PRICE_CAP
}

/// @notice Returns the error code for invalid optimal usage ratio
/// @return Error code as u64
public fun get_einvalid_optimal_usage_ratio(): u64 {
Expand Down
13 changes: 12 additions & 1 deletion aave-core/aave-config/tests/error_tests.move
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,8 @@ module aave_config::error_tests {
get_einvalid_growth_rate,
get_einvalid_snapshot_delay,
get_einvalid_snapshot_ratio,
get_einvalid_snapshot_timestamp
get_einvalid_snapshot_timestamp,
get_ecustom_price_above_price_cap
};

const TEST_SUCCESS: u64 = 1;
Expand Down Expand Up @@ -438,6 +439,8 @@ module aave_config::error_tests {
const EINVALID_SNAPSHOT_RATIO: u64 = 1227;
/// The snapshot timestamp is invalid
const EINVALID_SNAPSHOT_TIMESTAMP: u64 = 1228;
/// The assigned custom price is above the price cap
const ECUSTOM_PRICE_ABOVE_PRICE_CAP: u64 = 1229;

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

Expand Down Expand Up @@ -1314,6 +1317,14 @@ module aave_config::error_tests {
);
}

#[test]
public fun test_ecustom_price_above_price_cap() {
assert!(
get_ecustom_price_above_price_cap() == ECUSTOM_PRICE_ABOVE_PRICE_CAP,
TEST_SUCCESS
);
}

#[test]
public fun test_get_einvalid_ratio_timestamp() {
assert!(get_einvalid_ratio_timestamp() == EINVALID_RATIO_TIMESTAMP, TEST_SUCCESS);
Expand Down
7 changes: 7 additions & 0 deletions aave-core/aave-oracle/sources/oracle.move
Original file line number Diff line number Diff line change
Expand Up @@ -559,6 +559,13 @@ module aave_oracle::oracle {
) acquires PriceOracleData {
only_asset_listing_or_pool_admin(account);
assert!(custom_price > 0, error_config::get_ezero_asset_custom_price());
if (is_asset_price_capped(asset)) {
let (capped_price, _) = get_asset_price_and_timestamp(asset);
assert!(
custom_price <= capped_price,
error_config::get_ecustom_price_above_price_cap()
);
};
update_asset_custom_price(asset, custom_price);
}

Expand Down
285 changes: 285 additions & 0 deletions aave-core/aave-oracle/tests/oracle_tests.move
Original file line number Diff line number Diff line change
Expand Up @@ -984,6 +984,291 @@ module aave_oracle::oracle_tests {
);
}

#[
test(
super_admin = @aave_acl,
oracle_admin = @0x06,
aave_oracle = @aave_oracle,
data_feeds = @data_feeds,
platform = @platform,
aptos = @aptos_framework
)
]
fun test_oracle_set_stable_price_cap_adapter_success(
super_admin: &signer,
oracle_admin: &signer,
aave_oracle: &signer,
data_feeds: &signer,
platform: &signer,
aptos: &signer
) {
// start the timer
set_time_has_started_for_testing(aptos);

// init the acl module
acl_manage::test_init_module(super_admin);

// add the roles for the oracle admin
acl_manage::add_pool_admin(super_admin, signer::address_of(oracle_admin));
assert!(
acl_manage::is_pool_admin(signer::address_of(oracle_admin)), TEST_SUCCESS
);
acl_manage::add_asset_listing_admin(
super_admin, signer::address_of(oracle_admin)
);
assert!(
acl_manage::is_asset_listing_admin(signer::address_of(oracle_admin)),
TEST_SUCCESS
);

// init aave oracle
config_oracle(aave_oracle, data_feeds, platform);

// define asset and price cap
let asset_address = @0x0;
let asset_capped_price = 2 * TEST_FEED_PRICE;

// first set the CL feed for the asset
oracle::set_asset_feed_id(oracle_admin, asset_address, TEST_FEED_ID);

// set asset price cap (that succeeds because the cap is 2 * price asset)
oracle::set_price_cap_stable_adapter(
oracle_admin,
asset_address,
asset_capped_price
);

// check for specific events
let emitted_events = emitted_events<oracle::PriceCapUpdated>();
assert!(
vector::length(&emitted_events) == 1,
TEST_SUCCESS
);

// the asset price cap must be retrievable
assert!(
*option::borrow(&oracle::get_stable_price_cap(asset_address))
== asset_capped_price,
TEST_SUCCESS
);

// now simulate an increase of the price higher than the cap, i.e. price must be capped
let current_time = timestamp::now_seconds();
let fresh_timestamp = (current_time * 1000) as u256;
let new_increased_price = asset_capped_price + 1;
registry::perform_update_for_test(
TEST_FEED_ID,
fresh_timestamp,
new_increased_price,
vector::empty<u8>()
);

// asset is capped at this point
assert!(oracle::is_asset_price_capped(asset_address), TEST_SUCCESS);

// check the asset price
assert!(
oracle::get_asset_price(asset_address) == asset_capped_price,
TEST_SUCCESS
);
}

#[
test(
super_admin = @aave_acl,
oracle_admin = @0x06,
aave_oracle = @aave_oracle,
data_feeds = @data_feeds,
platform = @platform,
aptos = @aptos_framework
)
]
#[expected_failure(abort_code = 1229, location = aave_oracle::oracle)]
fun test_oracle_stable_price_cap_adapter_when_custom_price_higher_than_price_cap(
super_admin: &signer,
oracle_admin: &signer,
aave_oracle: &signer,
data_feeds: &signer,
platform: &signer,
aptos: &signer
) {
// start the timer
set_time_has_started_for_testing(aptos);

// init the acl module
acl_manage::test_init_module(super_admin);

// add the roles for the oracle admin
acl_manage::add_pool_admin(super_admin, signer::address_of(oracle_admin));
assert!(
acl_manage::is_pool_admin(signer::address_of(oracle_admin)), TEST_SUCCESS
);
acl_manage::add_asset_listing_admin(
super_admin, signer::address_of(oracle_admin)
);
assert!(
acl_manage::is_asset_listing_admin(signer::address_of(oracle_admin)),
TEST_SUCCESS
);

// init aave oracle
config_oracle(aave_oracle, data_feeds, platform);

// define asset and price cap
let asset_address = @0x0;
let asset_capped_price = 2 * TEST_FEED_PRICE;

// first set the CL feed for the asset
oracle::set_asset_feed_id(oracle_admin, asset_address, TEST_FEED_ID);

// set asset price cap (that succeeds because the cap is 2 * price asset)
oracle::set_price_cap_stable_adapter(
oracle_admin,
asset_address,
asset_capped_price
);

// check for specific events
let emitted_events = emitted_events<oracle::PriceCapUpdated>();
assert!(
vector::length(&emitted_events) == 1,
TEST_SUCCESS
);

// the asset price cap must be retrievable
assert!(
*option::borrow(&oracle::get_stable_price_cap(asset_address))
== asset_capped_price,
TEST_SUCCESS
);

// now simulate an increase of the price higher than the cap, i.e. price must be capped
let current_time = timestamp::now_seconds();
let fresh_timestamp = (current_time * 1000) as u256;
let new_increased_price = asset_capped_price + 1;
registry::perform_update_for_test(
TEST_FEED_ID,
fresh_timestamp,
new_increased_price,
vector::empty<u8>()
);

// asset is capped at this point
assert!(oracle::is_asset_price_capped(asset_address), TEST_SUCCESS);

// check the asset price
assert!(
oracle::get_asset_price(asset_address) == asset_capped_price,
TEST_SUCCESS
);

// try and set a custom price higher than the price cap
let new_custom_price = asset_capped_price + 1;
oracle::set_asset_custom_price(oracle_admin, asset_address, new_custom_price);
}

#[
test(
super_admin = @aave_acl,
oracle_admin = @0x06,
aave_oracle = @aave_oracle,
data_feeds = @data_feeds,
platform = @platform,
aptos = @aptos_framework
)
]
fun test_oracle_stable_price_cap_adapter_when_custom_price_lower_than_price_cap(
super_admin: &signer,
oracle_admin: &signer,
aave_oracle: &signer,
data_feeds: &signer,
platform: &signer,
aptos: &signer
) {
// start the timer
set_time_has_started_for_testing(aptos);

// init the acl module
acl_manage::test_init_module(super_admin);

// add the roles for the oracle admin
acl_manage::add_pool_admin(super_admin, signer::address_of(oracle_admin));
assert!(
acl_manage::is_pool_admin(signer::address_of(oracle_admin)), TEST_SUCCESS
);
acl_manage::add_asset_listing_admin(
super_admin, signer::address_of(oracle_admin)
);
assert!(
acl_manage::is_asset_listing_admin(signer::address_of(oracle_admin)),
TEST_SUCCESS
);

// init aave oracle
config_oracle(aave_oracle, data_feeds, platform);

// define asset and price cap
let asset_address = @0x0;
let asset_capped_price = 2 * TEST_FEED_PRICE;

// first set the CL feed for the asset
oracle::set_asset_feed_id(oracle_admin, asset_address, TEST_FEED_ID);

// set asset price cap (that succeeds because the cap is 2 * price asset)
oracle::set_price_cap_stable_adapter(
oracle_admin,
asset_address,
asset_capped_price
);

// check for specific events
let emitted_events = emitted_events<oracle::PriceCapUpdated>();
assert!(
vector::length(&emitted_events) == 1,
TEST_SUCCESS
);

// the asset price cap must be retrievable
assert!(
*option::borrow(&oracle::get_stable_price_cap(asset_address))
== asset_capped_price,
TEST_SUCCESS
);

// now simulate an increase of the price higher than the cap, i.e. price must be capped
let current_time = timestamp::now_seconds();
let fresh_timestamp = (current_time * 1000) as u256;
let new_increased_price = asset_capped_price + 1;
registry::perform_update_for_test(
TEST_FEED_ID,
fresh_timestamp,
new_increased_price,
vector::empty<u8>()
);

// asset is capped at this point
assert!(oracle::is_asset_price_capped(asset_address), TEST_SUCCESS);

// check the asset price
assert!(
oracle::get_asset_price(asset_address) == asset_capped_price,
TEST_SUCCESS
);

// try and set a custom price lower than the price cap
let new_custom_price = asset_capped_price - 1;
oracle::set_asset_custom_price(oracle_admin, asset_address, new_custom_price);

// check the asset price - must be the new custom price
assert!(
oracle::get_asset_price(asset_address) == new_custom_price,
TEST_SUCCESS
);

// asset is no longer capped at this point
assert!(!oracle::is_asset_price_capped(asset_address), TEST_SUCCESS);
}

#[
test(
super_admin = @aave_acl,
Expand Down
Loading