mirror of
https://github.com/serai-dex/serai.git
synced 2025-12-08 04:09:23 +00:00
If the pool has yet to start, insert a price of 0
The test failures were caused by not inserting any price, causing the first price to immediately become the oraclized price. While that's not inherently invalid, suggesting the tests should've been the ones updated, it opens an exploit where whoever first adds liquidity has the opportunity to set a ridiculous price and DoS the set. Not oraclizing until we have an entire period, achieved by inserting 0s during the initial blocks, ensures an open launch for such discovery.
This commit is contained in:
@@ -360,22 +360,23 @@ pub mod pallet {
|
|||||||
for coin in Pools::<T>::iter_keys() {
|
for coin in Pools::<T>::iter_keys() {
|
||||||
// insert the new price to our oracle window
|
// insert the new price to our oracle window
|
||||||
// The spot price for 1 coin, in atomic units, to SRI is used
|
// The spot price for 1 coin, in atomic units, to SRI is used
|
||||||
let Ok((sri_balance, coin_balance)) = Self::get_reserves(&Coin::native(), &coin) else {
|
let sri_per_coin =
|
||||||
continue;
|
if let Ok((sri_balance, coin_balance)) = Self::get_reserves(&Coin::native(), &coin) {
|
||||||
};
|
// We use 1 coin to handle rounding errors which may occur with atomic units
|
||||||
|
// If we used atomic units, any coin whose atomic unit is worth less than SRI's atomic
|
||||||
// We use 1 coin to handle rounding errors which may occur with atomic units
|
// unit would cause a 'price' of 0
|
||||||
// If we used atomic units, any coin whose atomic unit is worth less than SRI's atomic unit
|
// If the decimals aren't large enough to provide sufficient buffer, use 10,000
|
||||||
// would cause a 'price' of 0
|
let coin_decimals = coin.decimals().max(5);
|
||||||
// If the decimals aren't large enough to provide sufficient buffer, use 10,000
|
let accuracy_increase =
|
||||||
let coin_decimals = coin.decimals().max(5);
|
HigherPrecisionBalance::from(SubstrateAmount::pow(10, coin_decimals));
|
||||||
let accuracy_increase =
|
u64::try_from(
|
||||||
HigherPrecisionBalance::from(SubstrateAmount::pow(10, coin_decimals));
|
accuracy_increase * HigherPrecisionBalance::from(sri_balance) /
|
||||||
let sri_per_coin = u64::try_from(
|
HigherPrecisionBalance::from(coin_balance),
|
||||||
accuracy_increase * HigherPrecisionBalance::from(sri_balance) /
|
)
|
||||||
HigherPrecisionBalance::from(coin_balance),
|
.unwrap_or(u64::MAX)
|
||||||
)
|
} else {
|
||||||
.unwrap_or(u64::MAX);
|
0
|
||||||
|
};
|
||||||
let sri_per_coin = sri_per_coin.to_be_bytes();
|
let sri_per_coin = sri_per_coin.to_be_bytes();
|
||||||
|
|
||||||
SpotPriceForBlock::<T>::set(n, coin, sri_per_coin);
|
SpotPriceForBlock::<T>::set(n, coin, sri_per_coin);
|
||||||
@@ -393,7 +394,7 @@ pub mod pallet {
|
|||||||
SpotPriceForBlock::<T>::remove(start_of_window, coin);
|
SpotPriceForBlock::<T>::remove(start_of_window, coin);
|
||||||
// Remove this price from the multiset
|
// Remove this price from the multiset
|
||||||
OraclePrices::<T>::mutate_exists(coin, start_spot_price, |v| {
|
OraclePrices::<T>::mutate_exists(coin, start_spot_price, |v| {
|
||||||
*v = Some(v.unwrap() - 1);
|
*v = Some(v.unwrap_or(1) - 1);
|
||||||
if *v == Some(0) {
|
if *v == Some(0) {
|
||||||
*v = None;
|
*v = None;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user