Skip to content

Commit

Permalink
fix: try fixing bounds
Browse files Browse the repository at this point in the history
  • Loading branch information
MerlinEgalite committed Nov 13, 2023
1 parent 222b04e commit abf841b
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 19 deletions.
14 changes: 7 additions & 7 deletions src/SpeedJumpIrm.sol
Original file line number Diff line number Diff line change
Expand Up @@ -137,9 +137,9 @@ contract AdaptativeCurveIrm is IIrm {
int256 linearAdaptation = speed * int256(elapsed);
uint256 adaptationMultiplier = MathLib.wExp(linearAdaptation);
// endRateAtTarget is bounded between MIN_RATE_AT_TARGET and MAX_RATE_AT_TARGET.
uint256 endRateAtTarget =
startRateAtTarget.wMulDown(adaptationMultiplier).bound(MIN_RATE_AT_TARGET, MAX_RATE_AT_TARGET);
uint256 endBorrowRate = _curve(endRateAtTarget, err);
uint256 unboundedEndRateAtTarget = startRateAtTarget.wMulDown(adaptationMultiplier);
uint256 endRateAtTarget = unboundedEndRateAtTarget.bound(MIN_RATE_AT_TARGET, MAX_RATE_AT_TARGET);
uint256 endBorrowRate = _curve(unboundedEndRateAtTarget, err);

// Then we compute the average rate over the period.
// Note that startBorrowRate is defined in the computations below.
Expand All @@ -158,7 +158,7 @@ contract AdaptativeCurveIrm is IIrm {
avgBorrowRate = uint256((int256(endBorrowRate) - int256(startBorrowRate)).wDivDown(linearAdaptation));
}

return (avgBorrowRate, endRateAtTarget);
return (avgBorrowRate.bound(MIN_RATE_AT_TARGET, MAX_RATE_AT_TARGET), endRateAtTarget);
}
}

Expand All @@ -168,10 +168,10 @@ contract AdaptativeCurveIrm is IIrm {
/// ((C-1)*err + 1) * rateAtTarget else.
function _curve(uint256 _rateAtTarget, int256 err) private view returns (uint256) {
// Safe "unchecked" cast of _rateAtTarget because _rateAtTarget <= MAX_RATE_AT_TARGET.
int256 steeringCoeff = (err < 0 ? WAD_INT - WAD_INT.wDivDown(CURVE_STEEPNESS) : CURVE_STEEPNESS - WAD_INT)
.wMulDown(int256(_rateAtTarget));
int256 coeff = err < 0 ? WAD_INT - WAD_INT.wDivDown(CURVE_STEEPNESS) : CURVE_STEEPNESS - WAD_INT;

// Safe "unchecked" cast of _rateAtTarget because _rateAtTarget <= MAX_RATE_AT_TARGET.
// Safe "unchecked" cast of the result because r >= 0.
return uint256(steeringCoeff.wMulDown(err) + int256(_rateAtTarget));
return uint256(coeff.wMulDown(err) + WAD_INT).wMulDown(_rateAtTarget);
}
}
54 changes: 42 additions & 12 deletions test/SpeedJumpIrmTest.sol
Original file line number Diff line number Diff line change
Expand Up @@ -190,15 +190,49 @@ contract AdaptativeCurveIrmTest is Test {
);
}

function testNotUnbounded(uint256 startRateAtTarget, uint256 elapsed) public {
startRateAtTarget = bound(startRateAtTarget, irm.MIN_RATE_AT_TARGET(), irm.MAX_RATE_AT_TARGET());
elapsed = bound(elapsed, 0, 365 days);

int256 err = 1 ether;
int256 speed = ADJUSTMENT_SPEED.wMulDown(err);
uint256 adaptationMultiplier = MathLib.wExp(speed * int256(elapsed));

uint256 endRateAtTarget =
startRateAtTarget.wMulDown(adaptationMultiplier).bound(irm.MIN_RATE_AT_TARGET(), irm.MAX_RATE_AT_TARGET());
uint256 endBorrowRate = _curve(endRateAtTarget, err);
uint256 startBorrowRate = _curve(startRateAtTarget, err);

assertApproxEqAbs(startBorrowRate.wMulDown(adaptationMultiplier), endBorrowRate, 1e3);
}

function testUnbounded(uint256 startRateAtTarget, uint256 elapsed) public {
startRateAtTarget = bound(startRateAtTarget, irm.MIN_RATE_AT_TARGET(), irm.MAX_RATE_AT_TARGET());
elapsed = bound(elapsed, 0, 2 days);

int256 err = 1 ether;
int256 speed = ADJUSTMENT_SPEED.wMulDown(err);
uint256 adaptationMultiplier = MathLib.wExp(speed * int256(elapsed));

uint256 unboundedEndRateAtTarget = startRateAtTarget.wMulDown(adaptationMultiplier);
//uint256 endRateAtTarget = unboundedEndRateAtTarget.bound(irm.MIN_RATE_AT_TARGET(), irm.MAX_RATE_AT_TARGET());
uint256 endBorrowRate = _curve(unboundedEndRateAtTarget, err);
uint256 startBorrowRate = _curve(startRateAtTarget, err);

assertApproxEqAbs(startBorrowRate.wMulDown(adaptationMultiplier), endBorrowRate, 1e3);
}

function _expectedRateAtTarget(Id id, Market memory market) internal view returns (uint256) {
return _expectedUnboundedRateAtTarget(id, market).bound(irm.MIN_RATE_AT_TARGET(), irm.MAX_RATE_AT_TARGET());
}

function _expectedUnboundedRateAtTarget(Id id, Market memory market) internal view returns (uint256) {
uint256 rateAtTarget = irm.rateAtTarget(id);
int256 speed = ADJUSTMENT_SPEED.wMulDown(_err(market));
uint256 elapsed = (rateAtTarget > 0) ? block.timestamp - market.lastUpdate : 0;
int256 linearAdaptation = speed * int256(elapsed);
uint256 adaptationMultiplier = MathLib.wExp(linearAdaptation);
return (rateAtTarget > 0)
? rateAtTarget.wMulDown(adaptationMultiplier).bound(irm.MIN_RATE_AT_TARGET(), irm.MAX_RATE_AT_TARGET())
: INITIAL_RATE_AT_TARGET;
return (rateAtTarget > 0) ? rateAtTarget.wMulDown(adaptationMultiplier) : INITIAL_RATE_AT_TARGET;
}

function _expectedAvgRate(Id id, Market memory market) internal view returns (uint256) {
Expand All @@ -207,8 +241,8 @@ contract AdaptativeCurveIrmTest is Test {
int256 speed = ADJUSTMENT_SPEED.wMulDown(err);
uint256 elapsed = (rateAtTarget > 0) ? block.timestamp - market.lastUpdate : 0;
int256 linearAdaptation = speed * int256(elapsed);
uint256 endRateAtTarget = _expectedRateAtTarget(id, market);
uint256 newBorrowRate = _curve(endRateAtTarget, err);
uint256 unboundedEndRateAtTarget = _expectedUnboundedRateAtTarget(id, market);
uint256 newBorrowRate = _curve(unboundedEndRateAtTarget, err);

uint256 avgBorrowRate;
if (linearAdaptation == 0 || rateAtTarget == 0) {
Expand All @@ -218,19 +252,15 @@ contract AdaptativeCurveIrmTest is Test {
avgBorrowRate =
uint256((int256(newBorrowRate) - int256(_curve(rateAtTarget, err))).wDivDown(linearAdaptation));
}
return avgBorrowRate;
return avgBorrowRate.bound(irm.MIN_RATE_AT_TARGET(), irm.MAX_RATE_AT_TARGET());
}

function _curve(uint256 rateAtTarget, int256 err) internal pure returns (uint256) {
// Safe "unchecked" cast because err >= -1 (in WAD).
if (err < 0) {
return uint256(
(WAD_INT - WAD_INT.wDivDown(CURVE_STEEPNESS)).wMulDown(int256(rateAtTarget)).wMulDown(err)
+ int256(rateAtTarget)
);
return uint256((WAD_INT - WAD_INT.wDivDown(CURVE_STEEPNESS)).wMulDown(err) + WAD_INT).wMulDown(rateAtTarget);
} else {
return
uint256((CURVE_STEEPNESS - WAD_INT).wMulDown(int256(rateAtTarget)).wMulDown(err) + int256(rateAtTarget));
return uint256((CURVE_STEEPNESS - WAD_INT).wMulDown(err) + WAD_INT).wMulDown(rateAtTarget);
}
}

Expand Down

0 comments on commit abf841b

Please sign in to comment.