Skip to content

Commit 74defc0

Browse files
committed
fix: addresses #7
1 parent adbe551 commit 74defc0

File tree

8 files changed

+110
-72
lines changed

8 files changed

+110
-72
lines changed

src/ReservoirPriceOracle.sol

Lines changed: 10 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -207,21 +207,15 @@ contract ReservoirPriceOracle is IPriceOracle, Owned(msg.sender), ReentrancyGuar
207207
view
208208
returns (uint256 rReward)
209209
{
210-
// SAFETY: this mul will not overflow as 0 < `aRewardThreshold` <= `Constants.BP_SCALE`, as checked by `setRoute`
211-
uint256 lRewardThresholdWAD;
212-
unchecked {
213-
lRewardThresholdWAD = aRewardThreshold * Constants.WAD / Constants.BP_SCALE;
214-
}
215-
216210
uint256 lPercentDiff = aPrevPrice.calcPercentageDiff(aNewPrice);
217211

218212
// SAFETY: this mul will not overflow even in extreme cases of `block.basefee`.
219213
unchecked {
220-
if (lPercentDiff < lRewardThresholdWAD) {
214+
if (lPercentDiff < aRewardThreshold) {
221215
return 0;
222216
}
223217
// payout max reward
224-
else if (lPercentDiff >= lRewardThresholdWAD * MAX_REWARD_MULTIPLIER) {
218+
else if (lPercentDiff >= aRewardThreshold * MAX_REWARD_MULTIPLIER) {
225219
// N.B. Revisit this whenever deployment on a new chain is needed
226220
//
227221
// we use `block.basefee` instead of `ArbGasInfo::getMinimumGasPrice()`
@@ -230,7 +224,8 @@ contract ReservoirPriceOracle is IPriceOracle, Owned(msg.sender), ReentrancyGuar
230224
// congestion
231225
rReward = block.basefee * rewardGasAmount * MAX_REWARD_MULTIPLIER;
232226
} else {
233-
rReward = block.basefee * rewardGasAmount * lPercentDiff / lRewardThresholdWAD; // denominator is never 0
227+
// denominator is never 0 as checked by `setRoute`
228+
rReward = block.basefee * rewardGasAmount * lPercentDiff / aRewardThreshold;
234229
}
235230
}
236231
}
@@ -300,7 +295,7 @@ contract ReservoirPriceOracle is IPriceOracle, Owned(msg.sender), ReentrancyGuar
300295

301296
// Calculate the storage slot for this intermediate segment and read it to see if there is an existing
302297
// route. If there isn't an existing route, we create one as well.
303-
function _checkAndPopulateIntermediateRoute(address aTokenA, address aTokenB, uint16 aBpMaxReward) private {
298+
function _checkAndPopulateIntermediateRoute(address aTokenA, address aTokenB, uint64 aBpMaxReward) private {
304299
(address lToken0, address lToken1) = Utils.sortTokens(aTokenA, aTokenB);
305300

306301
bytes32 lSlot = Utils.calculateSlot(lToken0, lToken1);
@@ -312,9 +307,9 @@ contract ReservoirPriceOracle is IPriceOracle, Owned(msg.sender), ReentrancyGuar
312307
address[] memory lIntermediateRoute = new address[](2);
313308
lIntermediateRoute[0] = lToken0;
314309
lIntermediateRoute[1] = lToken1;
315-
uint16[] memory asd = new uint16[](1);
316-
asd[0] = aBpMaxReward;
317-
setRoute(lToken0, lToken1, lIntermediateRoute, asd);
310+
uint64[] memory lRewardThreshold = new uint64[](1);
311+
lRewardThreshold[0] = aBpMaxReward;
312+
setRoute(lToken0, lToken1, lIntermediateRoute, lRewardThreshold);
318313
}
319314
}
320315

@@ -488,7 +483,7 @@ contract ReservoirPriceOracle is IPriceOracle, Owned(msg.sender), ReentrancyGuar
488483
/// @param aToken1 Address of the higher token.
489484
/// @param aRoute Path with which the price between aToken0 and aToken1 should be derived.
490485
/// @param aRewardThresholds Array of basis points at and beyond which a reward is applicable for a price update.
491-
function setRoute(address aToken0, address aToken1, address[] memory aRoute, uint16[] memory aRewardThresholds)
486+
function setRoute(address aToken0, address aToken1, address[] memory aRoute, uint64[] memory aRewardThresholds)
492487
public
493488
onlyOwner
494489
{
@@ -511,7 +506,7 @@ contract ReservoirPriceOracle is IPriceOracle, Owned(msg.sender), ReentrancyGuar
511506

512507
uint256 lRewardThreshold = aRewardThresholds[0];
513508
require(
514-
lRewardThreshold <= Constants.BP_SCALE && lRewardThreshold != 0, OracleErrors.InvalidRewardThreshold()
509+
lRewardThreshold <= Constants.WAD && lRewardThreshold != 0, OracleErrors.InvalidRewardThreshold()
515510
);
516511

517512
bytes32 lData = RoutesLib.packSimplePrice(lDiff, 0, lRewardThreshold);

src/libraries/Constants.sol

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,9 @@ library Constants {
66
// CONSTANTS //
77
///////////////////////////////////////////////////////////////////////////////////////////////
88

9+
uint64 public constant WAD = 1e18;
910
uint256 public constant MAX_TWAP_PERIOD = 1 hours;
1011
uint256 public constant MAX_ROUTE_LENGTH = 4;
11-
uint256 public constant WAD = 1e18;
1212
uint256 public constant MAX_SUPPORTED_PRICE = type(uint128).max;
1313
uint256 public constant MAX_AMOUNT_IN = type(uint128).max;
14-
uint16 public constant BP_SCALE = 1e4;
1514
}

src/libraries/RoutesLib.sol

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,14 +29,14 @@ library RoutesLib {
2929

3030
// Assumes that aDecimalDifference is between -18 and 18
3131
// Assumes that aPrice is between 1 and `Constants.MAX_SUPPORTED_PRICE`
32-
// Assumes that aRewardThreshold is <= `Constants.BP_SCALE`
32+
// Assumes that aRewardThreshold is between 1 and `Constants.WAD`
3333
function packSimplePrice(int256 aDecimalDifference, uint256 aPrice, uint256 aRewardThreshold)
3434
internal
3535
pure
3636
returns (bytes32 rPacked)
3737
{
3838
bytes32 lDecimalDifferenceRaw = bytes1(uint8(int8(aDecimalDifference)));
39-
bytes32 lRewardThreshold = bytes2(uint16(aRewardThreshold));
39+
bytes32 lRewardThreshold = bytes8(uint64(aRewardThreshold));
4040
rPacked = FLAG_SIMPLE_PRICE | lDecimalDifferenceRaw >> 8 | lRewardThreshold >> 16 | bytes32(aPrice);
4141
}
4242

@@ -61,12 +61,12 @@ library RoutesLib {
6161
}
6262

6363
function getPrice(bytes32 aData) internal pure returns (uint256 rPrice) {
64-
rPrice = uint256(aData & 0x00000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff);
64+
rPrice = uint256(aData & 0x00000000000000000000ffffffffffffffffffffffffffffffffffffffffffff);
6565
}
6666

67-
function getRewardThreshold(bytes32 aData) internal pure returns (uint16 rRewardThreshold) {
67+
function getRewardThreshold(bytes32 aData) internal pure returns (uint64 rRewardThreshold) {
6868
rRewardThreshold =
69-
uint16(uint256((aData & 0x0000ffff00000000000000000000000000000000000000000000000000000000) >> 224));
69+
uint64(uint256((aData & 0x0000ffffffffffffffff00000000000000000000000000000000000000000000) >> 176));
7070
}
7171

7272
function getTokenFirstWord(bytes32 aData) internal pure returns (address rToken) {

src/libraries/Utils.sol

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ library Utils {
1414

1515
/// @dev Assumes that `aOriginal` and `aNew` is less than or equal to
1616
/// `Constants.MAX_SUPPORTED_PRICE`. So multiplication by 1e18 will not overflow.
17+
/// 1e18 indicates a 100% difference. i.e. a doubling in price
1718
function calcPercentageDiff(uint256 aOriginal, uint256 aNew) internal pure returns (uint256) {
1819
unchecked {
1920
if (aOriginal == 0) return 0;

test/large/ReservoirPriceOracleLarge.t.sol

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ contract ReservoirPriceOracleLargeTest is ReservoirPriceOracleTest {
7979
}
8080

8181
uint16[] memory lRewardThresholds = new uint16[](3);
82-
lRewardThresholds[0] = lRewardThresholds[1] = lRewardThresholds[2] = Constants.BP_SCALE;
82+
lRewardThresholds[0] = lRewardThresholds[1] = lRewardThresholds[2] = Constants.WAD;
8383

8484
_oracle.setRoute(lRoute[0], lRoute[3], lRoute, lRewardThresholds);
8585
_writePriceCache(

0 commit comments

Comments
 (0)