Skip to content

Commit

Permalink
Real math time
Browse files Browse the repository at this point in the history
  • Loading branch information
akshatmittal committed Jun 21, 2023
1 parent f14ea24 commit ba0c85a
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 14 deletions.
47 changes: 35 additions & 12 deletions contracts/libraries/Fixed.sol
Original file line number Diff line number Diff line change
Expand Up @@ -549,7 +549,7 @@ library FixLib {
return uint192(raw); // don't need _safeWrap
}

/// Muliplies two fixes and divides by a third
/// Multiplies two fixes and divide by a third
/// @param a First to multiply
/// @param b Second to multiply
/// @param c Denominator
Expand All @@ -558,23 +558,46 @@ library FixLib {
uint192 b,
uint192 c,
RoundingMode rounding
) internal pure returns (uint192) {
// return safeDiv(safeMul(a, b, CEIL), c, rounding);
// see safeMul and safeDiv for explanations
) internal pure returns (uint192 result) {
if (a == 0 || b == 0) return 0;
if (a == FIX_MAX || b == FIX_MAX || c == 0) return FIX_MAX;

uint256 result_256;
unchecked {
uint256 rawDelta = uint256(b) * a; // {D36} = {D18} * {D18}
// overflow
if (rawDelta / b != a) {
rawDelta = type(uint256).max;
(uint256 hi, uint256 lo) = fullMul(a, b);
if (hi >= c) return FIX_MAX;
uint256 mm = mulmod(a, b, c);
if (mm > lo) hi -= 1;
lo -= mm;
uint256 pow2 = c & (0 - c);

uint256 c_256 = uint256(c);
// Warning: Should not access c below this line

c_256 /= pow2;
lo /= pow2;
lo += hi * ((0 - pow2) / pow2 + 1);
uint256 r = 1;
r *= 2 - c_256 * r;
r *= 2 - c_256 * r;
r *= 2 - c_256 * r;
r *= 2 - c_256 * r;
r *= 2 - c_256 * r;
r *= 2 - c_256 * r;
r *= 2 - c_256 * r;
r *= 2 - c_256 * r;
result_256 = lo * r;

// Apply rounding
if (rounding == CEIL) {
if (mm > 0) result_256 += 1;
} else if (rounding == ROUND) {
if (mm > ((c_256 - 1) / 2)) result_256 += 1;
}
uint256 raw = _divrnd(rawDelta, uint256(c), rounding);
if (raw >= FIX_MAX) return FIX_MAX;

return uint192(raw);
}

if (result_256 >= FIX_MAX) return FIX_MAX;
return uint192(result_256);
}
}

Expand Down
3 changes: 1 addition & 2 deletions contracts/plugins/assets/RTokenAsset.sol
Original file line number Diff line number Diff line change
Expand Up @@ -186,8 +186,7 @@ contract RTokenAsset is IAsset, VersionedAsset, ModifiedChainlinkInterface {
cachedAtTime + ORACLE_TIMEOUT <= block.timestamp || // Cache Timeout
cachedAtNonce != basketHandler.nonce() // Basket nonce was updated
// !basketHandler.fullyCollateralized() // Basket is not fully collateralized
// TODO: Should we also check for ready?
// TODO: ..or status for that matter?
// Basket is recapitalizing, but there's not enough RSR.
) {
_updateCachedPrice();
}
Expand Down
30 changes: 30 additions & 0 deletions test/libraries/Fixed.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1053,6 +1053,36 @@ describe('In FixLib,', () => {
expect(
await caller.safeMulDiv(MAX_UINT192.sub(1), MAX_UINT192.sub(10), fp(1), CEIL)
).to.equal(MAX_UINT192)

expect(await caller.safeMulDiv(MAX_UINT192, MAX_UINT192, MAX_UINT192, FLOOR)).to.equal(
MAX_UINT192
)
expect(await caller.safeMulDiv(MAX_UINT192, MAX_UINT192, MAX_UINT192, ROUND)).to.equal(
MAX_UINT192
)
expect(await caller.safeMulDiv(MAX_UINT192, MAX_UINT192, MAX_UINT192, CEIL)).to.equal(
MAX_UINT192
)

expect(
await caller.safeMulDiv(MAX_UINT192.sub(1), MAX_UINT192.sub(10), MAX_UINT192.sub(1), FLOOR)
).to.equal(MAX_UINT192.sub(10))
expect(
await caller.safeMulDiv(MAX_UINT192.sub(1), MAX_UINT192.sub(10), MAX_UINT192.sub(1), ROUND)
).to.equal(MAX_UINT192.sub(10))
expect(
await caller.safeMulDiv(MAX_UINT192.sub(1), MAX_UINT192.sub(10), MAX_UINT192.sub(1), CEIL)
).to.equal(MAX_UINT192.sub(10))

expect(await caller.safeMulDiv(fp(1).sub(1), fp(1).add(1), fp(1).sub(1), FLOOR)).to.equal(
fp(1).add(1)
)
expect(await caller.safeMulDiv(fp(1).sub(1), fp(1).add(1), fp(1).sub(1), ROUND)).to.equal(
fp(1).add(1)
)
expect(await caller.safeMulDiv(fp(1).sub(1), fp(1).add(1), fp(1).sub(1), CEIL)).to.equal(
fp(1).add(1)
)
})

it('rounds up to FIX_MAX', async () => {
Expand Down

0 comments on commit ba0c85a

Please sign in to comment.