Skip to content

Commit

Permalink
Merge pull request #93 from Ion-Protocol/jun/PAG-M-04
Browse files Browse the repository at this point in the history
M-04 Fix [PAG]
  • Loading branch information
junkim012 authored May 16, 2024
2 parents 7802ed9 + 27e8d3b commit 226ebd8
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 3 deletions.
8 changes: 6 additions & 2 deletions src/InterestRate.sol
Original file line number Diff line number Diff line change
Expand Up @@ -325,9 +325,13 @@ contract InterestRate {
if (distributionFactor == 0) {
return (ilkData.minimumKinkRate, ilkData.reserveFactor.scaleUpToRay(4));
}

// If the `totalEthSupply` is small enough to truncate to zero, then
// treat the utilization as zero.
uint256 totalEthSupplyScaled = totalEthSupply.wadMulDown(distributionFactor.scaleUpToWad(4));

// [RAD] / [WAD] = [RAY]
uint256 utilizationRate =
totalEthSupply == 0 ? 0 : totalIlkDebt / (totalEthSupply.wadMulDown(distributionFactor.scaleUpToWad(4)));
uint256 utilizationRate = totalEthSupplyScaled == 0 ? 0 : totalIlkDebt / totalEthSupplyScaled;

// Avoid stack too deep
uint256 adjustedBelowKinkSlope;
Expand Down
76 changes: 76 additions & 0 deletions test/unit/concrete/IonPool.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -1193,6 +1193,82 @@ contract IonPool_InterestTest is IonPoolSharedSetup, IIonPoolEvents {
}
}

// If distribution factor is zero, should return
// minimum kink rate.
function test_DivideByZeroWhenDistributionFactorIsZero() public {
IlkData[] memory ilkConfigs = new IlkData[](2);
uint16[] memory distributionFactors = new uint16[](2);
distributionFactors[0] = 0;
distributionFactors[1] = 1e4;

uint96 minimumKinkRate = 4_062_570_058_138_700_000;
for (uint8 i; i != 2; ++i) {
IlkData memory ilkConfig = IlkData({
adjustedProfitMargin: 0,
minimumKinkRate: minimumKinkRate,
reserveFactor: 0,
adjustedBaseRate: 0,
minimumBaseRate: 0,
optimalUtilizationRate: 9000,
distributionFactor: distributionFactors[i],
adjustedAboveKinkSlope: 0,
minimumAboveKinkSlope: 0
});
ilkConfigs[i] = ilkConfig;
}

interestRateModule = new InterestRate(ilkConfigs, apyOracle);

vm.warp(block.timestamp + 1 days);

(uint256 zeroDistFactorBorrowRate,) = interestRateModule.calculateInterestRate(0, 10e45, 100e18); // 10%
// utilization
assertEq(zeroDistFactorBorrowRate, minimumKinkRate, "borrow rate should be minimum kink rate");

(uint256 nonZeroDistFactorBorrowRate,) = interestRateModule.calculateInterestRate(1, 100e45, 100e18); // 90%
// utilization
assertApproxEqAbs(
nonZeroDistFactorBorrowRate, minimumKinkRate, 1, "borrow rate at any util should be minimum kink rate"
);
}

// If scaling total eth supply with distribution factor truncates to zero,
// should return minimum base rate.
function test_DivideByZeroWhenTotalEthSupplyIsSmall() public {
IlkData[] memory ilkConfigs = new IlkData[](2);
uint16[] memory distributionFactors = new uint16[](2);
distributionFactors[0] = 0.5e4;
distributionFactors[1] = 0.5e4;

uint96 minimumKinkRate = 4_062_570_058_138_700_000;
uint96 minimumBaseRate = 1_580_630_071_273_960_000;
for (uint8 i; i != 2; ++i) {
IlkData memory ilkConfig = IlkData({
adjustedProfitMargin: 0,
minimumKinkRate: minimumKinkRate,
reserveFactor: 0,
adjustedBaseRate: 0,
minimumBaseRate: minimumBaseRate,
optimalUtilizationRate: 9000,
distributionFactor: distributionFactors[i],
adjustedAboveKinkSlope: 0,
minimumAboveKinkSlope: 0
});
ilkConfigs[i] = ilkConfig;
}

interestRateModule = new InterestRate(ilkConfigs, apyOracle);

vm.warp(block.timestamp + 1 days);

(uint256 borrowRate,) = interestRateModule.calculateInterestRate(0, 0, 1); // dust amount of eth supply
assertEq(borrowRate, minimumBaseRate, "borrow rate should be minimum base rate");

(uint256 borrowRateWithoutTruncation,) = interestRateModule.calculateInterestRate(1, 90e45, 100e18); // 90%
// utilization
assertApproxEqAbs(borrowRateWithoutTruncation, minimumKinkRate, 1, "borrow rate without truncation");
}

function test_AccrueInterestWhenPaused() public {
uint256 collateralDepositAmount = 10e18;
uint256 normalizedBorrowAmount = 5e18;
Expand Down
2 changes: 1 addition & 1 deletion test/unit/fuzz/vault/Vault.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { IIonPool } from "./../../../../src/interfaces/IIonPool.sol";
import { IonPoolExposed } from "../../../helpers/IonPoolSharedSetup.sol";
import { VaultSharedSetup } from "../../../helpers/VaultSharedSetup.sol";
import { Math } from "openzeppelin-contracts/contracts/utils/math/Math.sol";
import { RAY } from "./../../../../src/libraries/math/WadRayMath.sol";
import { WadRayMath, RAY } from "./../../../../src/libraries/math/WadRayMath.sol";
import { IERC20 } from "openzeppelin-contracts/contracts/interfaces/IERC20.sol";

using Math for uint256;
Expand Down

0 comments on commit 226ebd8

Please sign in to comment.